本帖最后由 FSL_TICS_Jeremy 于 2014-9-17 12:01 编辑
鼠标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[3] = 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
}
图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类特定请求。
******************************************************************************
*This function initializes the HID Class layer and layers it is dependent on
*****************************************************************************/
uint_8 USB_Class_HID_Init (
uint_8 controller_ID, /* [IN] Controller ID */
USB_CLASS_CALLBACK hid_class_callback, /* [IN] HID Class Callback */
USB_REQ_FUNC vendor_req_callback, /* [IN] 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[index].endpoint =
ep_desc_data->ep[index].ep_num;
g_hid_endpoint_data.ep[index].type =
ep_desc_data->ep[index].type;
g_hid_endpoint_data.ep[index].bin_consumer = 0x00;
g_hid_endpoint_data.ep[index].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 总线复位、枚举成功、配置变换、数据接收或发生完成。
***************************************************************************
[url=home.php?mod=space&uid=139335]@name[/url] USB_Class_Hid_Event
The funtion initializes the HID endpoints when Enumeration complete event is
received
***************************************************************************/
void USB_Class_Hid_Event (
uint_8 controller_ID, /* [IN] Controller ID */
uint_8 event, /* [IN] Event Type */
void* val /* [IN] 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[count];
/* Initializes sub_classes */
ep_count = dev_class_ptr->value[0];
if(dev_class_ptr->class_type == 0x03/*HID_CC*/)
break;
index_num +=dev_class_ptr->value[0];
}
/* 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[count]);
(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[count];
(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[index].bin_consumer = 0x00;
g_hid_endpoint_data.ep[index].bin_producer = 0x00;
g_hid_endpoint_data.ep[index].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, /* [IN] Controller ID */
USB_SETUP_STRUCT * setup_packet, /*[IN] Setup packet received */
uint_8_ptr *data, /* [OUT] Data to be send back */
USB_PACKET_SIZE *size /* [OUT] Size to be returned*/
)
{
uint_8 index;
uint_8 status = USBERR_INVALID_REQ_TYPE;
uint_8 rpt_buf[REPORT_SIZE];/* 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[0];
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[index] = *(*data + index);
}
break;
case USB_HID_GET_IDLE_REQUEST :
/* point to the current idle rate */
*data = &g_class_request_params[index];
*size = CLASS_REQ_DATA_SIZE;
break;
case USB_HID_SET_IDLE_REQUEST :
/* set the idle rate sent by the host */
g_class_request_params[index] =(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[index];
*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[index] = (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;
}
|