FSL_TICS_ZP 发表于 2014-9-16 22:47:43

【经验分享】鼠标HID例程简析(中)

鼠标HID例程简析

       今天紧接《鼠标HID例程简析(上)》一文,继续向大家介绍鼠标HID例程的未完的内容。

    TestApp_Init(void)

       TestApp_Init()函数包含USB_Class_HID_Init()函数实现USB接口的初始化,包括初始化各式USB类结构数据,并且通过其内部的USB_Class_Init()和USB_Device_Init()函数可分别初始化Class driver层中的Common class模块、Framework模块。
*****************************************************************************
* This function starts the Mouse Application
*****************************************************************************/

void TestApp_Init(void)
{
    uint_8   error;

    rpt_buf = 0x00; /* always zero */

    *((uint_32_ptr)rpt_buf) = 0;
    *((uint_32_ptr)null_buf) = 0;
    DisableInterrupts;
    #if (defined _MCF51MM256_H) || (defined _MCF51JE256_H)
   usb_int_dis();
    #endif       

    error = USB_Class_HID_Init(CONTROLLER_ID, USB_App_Callback, NULL,
                            USB_App_Param_Callback);//USB接口初始化
    UNUSED(error);
   
    EnableInterrupts;
    #if (defined _MCF51MM256_H) || (defined _MCF51JE256_H)
   usb_int_en();
    #endif       
}

       USB_Class_HID_Init()
    本人在《FSL USB Stack简介》一文中,已向大家介绍过USB Stack 架构中各层的组成和相互之间的关系,如图1所示。

图1 FSL USB Stack架构
      Framework模块:负责处理 USB device 在枚举过程中的控制
端点接到的来自Host的各式请求。
    Common class 模块:负责处理所有USB 类都会发生的suspend/resume、reset、stall、SOF。当检测到事件发送时,如 USB
总线复位、枚举成功、配置变换、数据接收或发生完成等,Common class 模块都会通过传送Callback通知Class specific 模块或者USB Application层。
    Class specific模块用于处理控制端点外的端点与Host通信的事宜,在这类端点上进行字符发送和接收都受Class specific模块管理,同时Class specific模块还会处理在控制端点上接收到的特定请
求,如本例程中的HID类的特定请求:Get_Report、Set_Report 、Get_Idle、 Set_Idle 、Get_Protocol 、Set_Protocol。
    USB_Class_HID_Init()函数的函数指针参数:hid_class_callback、vendor_req_callback、param_callback分别对应着处理USB事件,Vendor特定请求,USB类特定请求。
******************************************************************************
*This function initializes the HID Class layer and layers it is dependent on
*****************************************************************************/
uint_8 USB_Class_HID_Init (
    uint_8    controller_ID,                /* Controller ID */
    USB_CLASS_CALLBACK hid_class_callback,/* HID Class Callback */
    USB_REQ_FUNC       vendor_req_callback, /* Vendor Request Callback */
    USB_CLASS_SPECIFIC_HANDLER_FUNC param_callback
                                        /* [ IN] HID Class requests Callback */
)
{
    uint_8 index,status = USB_OK;
    USB_ENDPOINTS *ep_desc_data = (USB_ENDPOINTS *)
      USB_Desc_Get_Endpoints(controller_ID);
   
#ifndef COMPOSITE_DEV
    /* Initialize the device layer*/
    status = _usb_device_init(controller_ID, NULL,
      (uint_8)(ep_desc_data->count+1), TRUE);
    if(status == USB_OK)
    {
      /* Initialize the generic class functions */
      status = USB_Class_Init(controller_ID,USB_Class_Hid_Event,
            USB_Other_Requests);

      if(status == USB_OK)
      {
#endif
            g_hid_endpoint_data.count = ep_desc_data->count;

            for(index = 0; index < ep_desc_data->count; index++)
            {
                g_hid_endpoint_data.ep.endpoint =
                  ep_desc_data->ep.ep_num;
                g_hid_endpoint_data.ep.type =
                  ep_desc_data->ep.type;
                g_hid_endpoint_data.ep.bin_consumer = 0x00;
                g_hid_endpoint_data.ep.bin_producer = 0x00;
            }

            /* save the HID class callback pointer */
            g_hid_class_callback = hid_class_callback;

            /* save the vendor request callback pointer */
            g_vendor_req_callback = vendor_req_callback;

            /* Save the callback to ask application for class specific params*/
            g_param_callback = param_callback;
#ifndef COMPOSITE_DEV
      }
    }
#endif
    return status;
}

    USB_Class_Hid_Event()
    USB_Class_Hid_Event对应着处理各式USB事件,如USB 总线复位、枚举成功、配置变换、数据接收或发生完成。
***************************************************************************
@nameUSB_Class_Hid_Event
The funtion initializes the HID endpoints when Enumeration complete event is
received
***************************************************************************/
void USB_Class_Hid_Event (
    uint_8 controller_ID,   /* Controller ID */
    uint_8 event,         /* Event Type */
    void* val               /* Pointer to configuration Value */
)
{
    uint_8 index;

    if(event == USB_APP_ENUM_COMPLETE)
    {
      uint_8 index_num = 0;
      uint_8 count = 0,ep_count = 0;
      USB_ENDPOINTS *ep_desc_data;
      
#ifdef COMPOSITE_DEV
      DEV_ARCHITECTURE_STRUCT_PTR dev_arc_ptr;
      CLASS_ARC_STRUCT_PTR dev_class_ptr;   
      dev_arc_ptr = (DEV_ARCHITECTURE_STRUCT *)USB_Desc_Get_Class_Architecture(controller_ID);   
      for(count = 0; count < dev_arc_ptr->cl_count; count++)
      {
            dev_class_ptr = (CLASS_ARC_STRUCT_PTR)dev_arc_ptr->value;
            /* Initializes sub_classes */
            ep_count = dev_class_ptr->value;
            if(dev_class_ptr->class_type == 0x03/*HID_CC*/)
                break;
            index_num +=dev_class_ptr->value;
      }
      /* get the endpoints from the descriptor module */
      ep_desc_data = (USB_ENDPOINTS *)USB_Desc_Get_Endpoints(controller_ID);
#else
      /* get the endpoints from the descriptor module */
      ep_desc_data = (USB_ENDPOINTS *)USB_Desc_Get_Endpoints(controller_ID);
                                    
                ep_count = ep_desc_data->count;
#endif
                /* deinitialize all endpoints in case they were initialized */
                for(count=index_num;count<ep_count+index_num;count++)
                {   
                        USB_EP_STRUCT_PTR ep_struct_ptr=
                                (USB_EP_STRUCT_PTR) (&ep_desc_data->ep);
                        (void)_usb_device_deinit_endpoint(&controller_ID,
                                ep_struct_ptr->ep_num, ep_struct_ptr->direction);
                }

      /* intialize all non control endpoints */
      for(count=index_num;count<ep_count+index_num;count++)
      {
            USB_EP_STRUCT_PTR ep_struct=
                (USB_EP_STRUCT_PTR)&ep_desc_data->ep;

            (void)_usb_device_init_endpoint(&controller_ID, ep_struct->ep_num,
                            ep_struct->size, ep_struct->direction, ep_struct->type,
                            TRUE);

            /* register callback service for the endpoint */
            (void)_usb_device_register_service(controller_ID,
                                  (uint_8)(USB_SERVICE_EP0+ep_struct->ep_num),
                                                             USB_Service_Hid);


            /* set the EndPoint Status as Idle in the device layer */
            (void)_usb_device_set_status(&controller_ID,
                (uint_8)(USB_STATUS_ENDPOINT | ep_struct->ep_num |
                (ep_struct->direction << USB_COMPONENT_DIRECTION_SHIFT)),
                USB_STATUS_IDLE);
      }

    }
    else if((event == USB_APP_BUS_RESET) || (event == USB_APP_CONFIG_CHANGED))
    {
      /* clear producer and consumer on reset */
      for(index = 0; index < g_hid_endpoint_data.count; index++)
      {
            g_hid_endpoint_data.ep.bin_consumer = 0x00;
            g_hid_endpoint_data.ep.bin_producer = 0x00;
            g_hid_endpoint_data.ep.queue_num    = 0x00;
      }
    }

    if(g_hid_class_callback != NULL)
    {
      /* notify the application of the event */
      g_hid_class_callback(controller_ID, event, val);
    }

}


   USB_Other_Requests()
    USB_Other_Requests()函数用于处理Host发送来的HID类特定请求和Vendor特定请求,如,Get_Report、Set_Report 、Get_Idle、 Set_Idle 、Get_Protocol 、Set_Protocol。
******************************************************************************
* Handles HID Class requests and forwards vendor specific request to the
* application
*****************************************************************************/
#ifndef COMPOSITE_DEV
static uint_8 USB_Other_Requests
#else
uint_8 USB_HID_Other_Requests
#endif
(
    uint_8 controller_ID,               /* Controller ID */
    USB_SETUP_STRUCT * setup_packet,    /* Setup packet received */
    uint_8_ptr *data,                   /* Data to be send back */
    USB_PACKET_SIZE *size               /* Size to be returned*/
)
{
    uint_8 index;
    uint_8 status = USBERR_INVALID_REQ_TYPE;
    uint_8 rpt_buf;/* buffer to send in case of get report req */
    *((uint_32_ptr)rpt_buf) = 0;

    if((setup_packet->request_type & USB_REQUEST_CLASS_MASK) ==
      USB_REQUEST_CLASS_CLASS)
    {
      /* class request so handle it here */
      /* index == 0 for get/set idle, index == 1 for get/set protocol */
      index = (uint_8)((setup_packet->request - 2) &
            USB_HID_REQUEST_TYPE_MASK);

      status = USB_OK;
      /* point to the data which comes after the setup packet */
      *data = ((uint_8*)setup_packet) + USB_SETUP_PKT_SIZE;
      *size = 0;
      /* handle the class request */
      switch(setup_packet->request)
      {
            case USB_HID_GET_REPORT_REQUEST :
                /*set the data pointer to the buffer to send */
                *data = &rpt_buf;
                if(*size > REPORT_SIZE) *size = REPORT_SIZE;
                break;

            case USB_HID_SET_REPORT_REQUEST :
                for(index = 0; index < REPORT_SIZE; index++)
                {   /* copy the data sent by host in the buffer */
                  rpt_buf = *(*data + index);
                }
                break;

            case USB_HID_GET_IDLE_REQUEST :
                /* point to the current idle rate */
                *data = &g_class_request_params;
                *size = CLASS_REQ_DATA_SIZE;
                break;

            case USB_HID_SET_IDLE_REQUEST :
                /* set the idle rate sent by the host */
                g_class_request_params =(uint_8)((setup_packet->value
                  & MSB_MASK) >> HIGH_BYTE_SHIFT);
                break;

            case USB_HID_GET_PROTOCOL_REQUEST :
                /* point to the current protocol code
                            0 = Boot Protocol
                            1 = Report Protocol*/
                *data = &g_class_request_params;
                *size = CLASS_REQ_DATA_SIZE;
                break;

            case USB_HID_SET_PROTOCOL_REQUEST :
                /* set the protocol sent by the host
                           0 = Boot Protocol
                           1 = Report Protocol*/
                g_class_request_params = (uint_8)(setup_packet->value);
                break;
            default :
                break;
      }

      if(g_param_callback != NULL)
      {
            /*
               handle callback if the application has supplied it
               set the size of the transfer from the setup packet
            */
            *size = (USB_PACKET_SIZE)setup_packet->length;

            /* notify the application of the class request.
               give control to the application */
            status = g_param_callback(setup_packet->request,/* request type */
                setup_packet->value,
                setup_packet->index, /* Application needs to know which Interface is being communicated with */
                data,/* pointer to the data */
                size);/* size of the transfer */
      }

    }
    else if((setup_packet->request_type & USB_REQUEST_CLASS_MASK) ==
      USB_REQUEST_CLASS_VENDOR)
    {
      /* vendor specific request*/
      if(g_vendor_req_callback != NULL)
      {
            status = g_vendor_req_callback(controller_ID, setup_packet,data,
                size);
      }
    }
    return status;
}


参考文献:
Freescale USB Device Stack Users Guide
Freescale USB Stack Device API Reference Manual
FSL USB Stack v4.1.1

FSL_TICS_ZP 发表于 2014-9-18 09:01:38

如有什么错误或者不足,欢迎网友指正,请在后面跟帖!

32MCU 发表于 2014-9-18 09:09:00

顶一下。楼主辛苦了。

weiwei4 发表于 2014-9-18 10:52:51

谢谢版主分析得这么详细
现在对USB这个很头痛,要把USB的看熟了才行啊

FSL_TICS_ZP 发表于 2014-9-18 13:38:05

本帖最后由 FSL_TICS_ZP 于 2014-9-18 13:50 编辑

weiwei4 发表于 2014-9-18 10:52
谢谢版主分析得这么详细
现在对USB这个很头痛,要把USB的看熟了才行啊

有问题,可以交流交流!
页: [1]
查看完整版本: 【经验分享】鼠标HID例程简析(中)