查看: 1938|回复: 5

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

[复制链接]

该用户从未签到

124

主题

3600

帖子

0

金牌会员

Rank: 6Rank: 6

积分
5781
最后登录
1970-1-1
发表于 2014-9-16 17:29:41 | 显示全部楼层 |阅读模式
本帖最后由 FSL_TICS_ZP 于 2014-9-16 17:43 编辑

鼠标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模块。
  1. *****************************************************************************
  2. * This function starts the Mouse Application
  3. *****************************************************************************/

  4. void TestApp_Init(void)
  5. {
  6.     uint_8   error;

  7.     rpt_buf[3] = 0x00; /* always zero */

  8.     *((uint_32_ptr)rpt_buf) = 0;
  9.     *((uint_32_ptr)null_buf) = 0;
  10.     DisableInterrupts;
  11.     #if (defined _MCF51MM256_H) || (defined _MCF51JE256_H)
  12.      usb_int_dis();
  13.     #endif        

  14.     error = USB_Class_HID_Init(CONTROLLER_ID, USB_App_Callback, NULL,
  15.                             USB_App_Param_Callback);//USB接口初始化
  16.     UNUSED(error);
  17.    
  18.     EnableInterrupts;
  19.     #if (defined _MCF51MM256_H) || (defined _MCF51JE256_H)
  20.      usb_int_en();
  21.     #endif        
  22. }
复制代码
      USB_Class_HID_Init()
本人在《FSL USB Stack简介》一文中,已向大家介绍过USB Stack 架构中各层的组成和相互之间的关系,如图1所示。
4.jpg
图1 FSL USB Stack架构
       Framework模块:负责处理 USB device 在枚举过程中的控制端点接到的来自Host的各式请求。
       Commonclass 模块:负责处理所有USB 类都会发生的suspend/resume、reset、stall、SOF。当检测到事件发送时,如USB总线复位、枚举成功、配置变换、数据接收或发生完成等,Common class 模块都会通过传送Callback通知Class specific 模块或者USB Application层。
      Classspecific模块用于处理控制端点外的端点与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类特定请求。
  1. ******************************************************************************
  2. *This function initializes the HID Class layer and layers it is dependent on
  3. *****************************************************************************/
  4. uint_8 USB_Class_HID_Init (
  5.     uint_8    controller_ID,                /* [IN] Controller ID */
  6.     USB_CLASS_CALLBACK hid_class_callback,  /* [IN] HID Class Callback */
  7.     USB_REQ_FUNC       vendor_req_callback, /* [IN] Vendor Request Callback */
  8.     USB_CLASS_SPECIFIC_HANDLER_FUNC param_callback
  9.                                         /* [ IN] HID Class requests Callback */
  10. )
  11. {
  12.     uint_8 index,status = USB_OK;
  13.     USB_ENDPOINTS *ep_desc_data = (USB_ENDPOINTS *)
  14.         USB_Desc_Get_Endpoints(controller_ID);
  15.    
  16. #ifndef COMPOSITE_DEV
  17.     /* Initialize the device layer*/
  18.     status = _usb_device_init(controller_ID, NULL,
  19.         (uint_8)(ep_desc_data->count+1), TRUE);
  20.     if(status == USB_OK)
  21.     {
  22.         /* Initialize the generic class functions */
  23.         status = USB_Class_Init(controller_ID,USB_Class_Hid_Event,
  24.             USB_Other_Requests);

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

  29.             for(index = 0; index < ep_desc_data->count; index++)
  30.             {
  31.                 g_hid_endpoint_data.ep[index].endpoint =
  32.                     ep_desc_data->ep[index].ep_num;
  33.                 g_hid_endpoint_data.ep[index].type =
  34.                     ep_desc_data->ep[index].type;
  35.                 g_hid_endpoint_data.ep[index].bin_consumer = 0x00;
  36.                 g_hid_endpoint_data.ep[index].bin_producer = 0x00;
  37.             }

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

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

  42.             /* Save the callback to ask application for class specific params*/
  43.             g_param_callback = param_callback;
  44. #ifndef COMPOSITE_DEV
  45.         }
  46.     }
  47. #endif
  48.     return status;
  49. }
复制代码
       USB_Class_Hid_Event()
USB_Class_Hid_Event对应着处理各式USB事件,如USB 总线复位、枚举成功、配置变换、数据接收或发生完成。
  1. ***************************************************************************
  2. @name  USB_Class_Hid_Event
  3.   The funtion initializes the HID endpoints when Enumeration complete event is
  4.   received
  5. ***************************************************************************/
  6. void USB_Class_Hid_Event (
  7.     uint_8 controller_ID,   /* [IN] Controller ID */
  8.     uint_8 event,           /* [IN] Event Type */
  9.     void* val               /* [IN] Pointer to configuration Value */
  10. )
  11. {
  12.     uint_8 index;

  13.     if(event == USB_APP_ENUM_COMPLETE)
  14.     {
  15.         uint_8 index_num = 0;
  16.         uint_8 count = 0,ep_count = 0;
  17.         USB_ENDPOINTS *ep_desc_data;  
  18.         
  19. #ifdef COMPOSITE_DEV
  20.         DEV_ARCHITECTURE_STRUCT_PTR dev_arc_ptr;
  21.         CLASS_ARC_STRUCT_PTR dev_class_ptr;   
  22.         dev_arc_ptr = (DEV_ARCHITECTURE_STRUCT *)USB_Desc_Get_Class_Architecture(controller_ID);   
  23.         for(count = 0; count < dev_arc_ptr->cl_count; count++)
  24.         {
  25.             dev_class_ptr = (CLASS_ARC_STRUCT_PTR)dev_arc_ptr->value[count];
  26.             /* Initializes sub_classes */
  27.             ep_count = dev_class_ptr->value[0];
  28.             if(dev_class_ptr->class_type == 0x03/*HID_CC*/)
  29.                 break;
  30.             index_num +=dev_class_ptr->value[0];
  31.         }
  32.         /* get the endpoints from the descriptor module */
  33.         ep_desc_data = (USB_ENDPOINTS *)USB_Desc_Get_Endpoints(controller_ID);
  34. #else
  35.         /* get the endpoints from the descriptor module */
  36.         ep_desc_data = (USB_ENDPOINTS *)USB_Desc_Get_Endpoints(controller_ID);
  37.                                        
  38.                 ep_count = ep_desc_data->count;
  39. #endif
  40.                 /* deinitialize all endpoints in case they were initialized */
  41.                 for(count=index_num;count<ep_count+index_num;count++)
  42.                 {   
  43.                         USB_EP_STRUCT_PTR ep_struct_ptr=
  44.                                 (USB_EP_STRUCT_PTR) (&ep_desc_data->ep[count]);
  45.                         (void)_usb_device_deinit_endpoint(&controller_ID,
  46.                                 ep_struct_ptr->ep_num, ep_struct_ptr->direction);  
  47.                 }

  48.         /* intialize all non control endpoints */
  49.         for(count=index_num;count<ep_count+index_num;count++)
  50.         {
  51.             USB_EP_STRUCT_PTR ep_struct=
  52.                 (USB_EP_STRUCT_PTR)&ep_desc_data->ep[count];

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

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


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

  66.     }
  67.     else if((event == USB_APP_BUS_RESET) || (event == USB_APP_CONFIG_CHANGED))
  68.     {
  69.         /* clear producer and consumer on reset */
  70.         for(index = 0; index < g_hid_endpoint_data.count; index++)
  71.         {
  72.             g_hid_endpoint_data.ep[index].bin_consumer = 0x00;
  73.             g_hid_endpoint_data.ep[index].bin_producer = 0x00;
  74.             g_hid_endpoint_data.ep[index].queue_num    = 0x00;
  75.         }
  76.     }

  77.     if(g_hid_class_callback != NULL)
  78.     {
  79.         /* notify the application of the event */
  80.         g_hid_class_callback(controller_ID, event, val);
  81.     }

  82. }
复制代码
USB_Other_Requests()
USB_Other_Requests()函数用于处理Host发送来的HID类特定请求和Vendor特定请求,如,Get_Report、Set_Report 、Get_Idle、 Set_Idle 、Get_Protocol、Set_Protocol。
  1. ******************************************************************************
  2. * Handles HID Class requests and forwards vendor specific request to the
  3. * application
  4. *****************************************************************************/
  5. #ifndef COMPOSITE_DEV
  6. static uint_8 USB_Other_Requests
  7. #else
  8. uint_8 USB_HID_Other_Requests
  9. #endif
  10. (
  11.     uint_8 controller_ID,               /* [IN] Controller ID */
  12.     USB_SETUP_STRUCT * setup_packet,    /*[IN] Setup packet received */
  13.     uint_8_ptr *data,                   /* [OUT] Data to be send back */
  14.     USB_PACKET_SIZE *size               /* [OUT] Size to be returned*/
  15. )
  16. {
  17.     uint_8 index;
  18.     uint_8 status = USBERR_INVALID_REQ_TYPE;
  19.     uint_8 rpt_buf[REPORT_SIZE];/* buffer to send in case of get report req */
  20.     *((uint_32_ptr)rpt_buf) = 0;

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

  28.         status = USB_OK;
  29.         /* point to the data which comes after the setup packet */
  30.         *data = ((uint_8*)setup_packet) + USB_SETUP_PKT_SIZE;
  31.         *size = 0;
  32.         /* handle the class request */
  33.         switch(setup_packet->request)
  34.         {
  35.             case USB_HID_GET_REPORT_REQUEST :
  36.                 /*set the data pointer to the buffer to send */
  37.                 *data = &rpt_buf[0];
  38.                 if(*size > REPORT_SIZE) *size = REPORT_SIZE;
  39.                 break;

  40.             case USB_HID_SET_REPORT_REQUEST :
  41.                 for(index = 0; index < REPORT_SIZE; index++)
  42.                 {   /* copy the data sent by host in the buffer */
  43.                   rpt_buf[index] = *(*data + index);
  44.                 }
  45.                 break;

  46.             case USB_HID_GET_IDLE_REQUEST :
  47.                 /* point to the current idle rate */
  48.                 *data = &g_class_request_params[index];
  49.                 *size = CLASS_REQ_DATA_SIZE;
  50.                 break;

  51.             case USB_HID_SET_IDLE_REQUEST :
  52.                 /* set the idle rate sent by the host */
  53.                 g_class_request_params[index] =(uint_8)((setup_packet->value
  54.                     & MSB_MASK) >> HIGH_BYTE_SHIFT);
  55.                 break;

  56.             case USB_HID_GET_PROTOCOL_REQUEST :
  57.                 /* point to the current protocol code
  58.                             0 = Boot Protocol
  59.                             1 = Report Protocol*/
  60.                 *data = &g_class_request_params[index];
  61.                 *size = CLASS_REQ_DATA_SIZE;
  62.                 break;

  63.             case USB_HID_SET_PROTOCOL_REQUEST :
  64.                 /* set the protocol sent by the host
  65.                              0 = Boot Protocol
  66.                              1 = Report Protocol*/
  67.                 g_class_request_params[index] = (uint_8)(setup_packet->value);
  68.                 break;
  69.             default :
  70.                 break;
  71.         }

  72.         if(g_param_callback != NULL)
  73.         {
  74.             /*
  75.                handle callback if the application has supplied it
  76.                set the size of the transfer from the setup packet
  77.             */
  78.             *size = (USB_PACKET_SIZE)setup_packet->length;

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

  87.     }
  88.     else if((setup_packet->request_type & USB_REQUEST_CLASS_MASK) ==
  89.         USB_REQUEST_CLASS_VENDOR)
  90.     {
  91.         /* vendor specific request  */
  92.         if(g_vendor_req_callback != NULL)
  93.         {
  94.             status = g_vendor_req_callback(controller_ID, setup_packet,data,
  95.                 size);
  96.         }
  97.     }
  98.     return status;
  99. }
复制代码
参考文献:

[size=19.0909080505371px]完整文档下载:
[size=19.0909080505371px] 鼠标HID例程(中).pdf (380.4 KB, 下载次数: 116)
回复

使用道具 举报

该用户从未签到

16

主题

705

帖子

0

金牌会员

Rank: 6Rank: 6

积分
1745
最后登录
1970-1-1
发表于 2014-9-16 17:34:56 | 显示全部楼层
感谢楼主对于USB stack的详细讲解,受教了。
回复 支持 反对

使用道具 举报

该用户从未签到

124

主题

3600

帖子

0

金牌会员

Rank: 6Rank: 6

积分
5781
最后登录
1970-1-1
 楼主| 发表于 2014-9-16 17:37:25 | 显示全部楼层
未完待续,
不足之处恳请指正,同时也欢迎大家分享自己的经验。
回复 支持 反对

使用道具 举报

该用户从未签到

5

主题

273

帖子

0

高级会员

Rank: 4

积分
718
最后登录
1970-1-1
发表于 2014-9-16 17:42:29 | 显示全部楼层
又有更新,谢谢斑竹分享!
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2014-9-17 11:10:36 | 显示全部楼层
大家以后有好的经验,也欢迎分享出来。
回复 支持 反对

使用道具 举报

该用户从未签到

124

主题

3600

帖子

0

金牌会员

Rank: 6Rank: 6

积分
5781
最后登录
1970-1-1
 楼主| 发表于 2014-10-8 10:04:29 | 显示全部楼层
Jay-295455 发表于 2014-9-16 17:42
又有更新,谢谢斑竹分享!

谢谢支持,如有疑问,请在帖子后面留贴!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /4 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2024-4-26 14:07 , Processed in 0.124358 second(s), 24 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表