本帖最后由 FSL_TICS_Jeremy 于 2014-9-18 17:05 编辑
鼠标HID例程简析 前两天已经陆续分享了两篇帖子来介绍鼠标HID例程,今天再接再励继续扫尾工作。闲话少叙,马上开整。 TestApp_Init() 在TestApp_Init()函数内,通过Emulate_Mouse_WithButton() 函数来模拟鼠标各式功能:左击、右击,上移、下移,左移、右移,而其中的USB_Class_HID_Send_Data()函数用于实现中断端点与Host PC进行数据通信。
*****************************************************************************
* Application task function. It is called from the main loop
*****************************************************************************/
void TestApp_Task(void)
{
/* call the periodic task function */
USB_Class_HID_Periodic_Task();
if(mouse_init) /*check whether enumeration is
complete or not */
{
/* run the button emulation code */
Emulate_Mouse_WithButton();
}
}
Emulate_Mouse_WithButton() 在本例程中,通过连接PTA4脚的SW3按键来模拟鼠标的右键,当然像鼠标的左击、上移、下移,左移、右移功能,也可通过SW3按键进行操作,而实现以上功能的关键就是:需要网友朋友们在理解鼠标报表描述符的基础上修改数据,并将其传递给中断端点。对报表描述符的介绍就不在本文展开啊,不了解的网友可以去参考先前分享的《USBHID设备应用(进阶篇)》一文。 *****************************************************************************
* This function sends the mouse data depending on which key was pressed on
* the board
*****************************************************************************/
static void Emulate_Mouse_WithButton(void)
{
if(kbi_stat > 0)
{
switch(kbi_stat & KBI_STAT_MASK)
{
case LEFT_CLICK : /* PTG0 (left click) is pressed */
rpt_buf[0] = LEFT_CLICK;
rpt_buf[1] = 0x00;
rpt_buf[2] = 0x00;
break;
case RIGHT_CLICK : /* PTG1 (right click) is pressed */
rpt_buf[0] = RIGHT_CLICK;
rpt_buf[1] = 0x00;
rpt_buf[2] = 0x00;
break;
case MOVE_LEFT_RIGHT : /* PTG2 (left
or right movement--depends on
UP_LEFT macro) is pressed*/
rpt_buf[1] = SHIFT_VAL;
rpt_buf[0] = 0x00;
rpt_buf[2] = 0x00;
break;
case MOVE_UP_DOWN : /* PTG3 (up or down
movement--depends on
UP_LEFT macro) is pressed*/
rpt_buf[2] = SHIFT_VAL;
rpt_buf[1] = 0x00;
rpt_buf[0] = 0x00;
break;
default:break; /* otherwise */
}
kbi_stat = 0x00; /* reset status after servicing interrupt*/
(void)USB_Class_HID_Send_Data(CONTROLLER_ID,HID_ENDPOINT,rpt_buf,
MOUSE_BUFF_SIZE);
if(rpt_buf[0])
{
/* required to send Click Release for Click Press Events */
(void)USB_Class_HID_Send_Data(CONTROLLER_ID,HID_ENDPOINT,null_buf,
MOUSE_BUFF_SIZE);
}
}
return;
}
IRQ_ISR_PORTA() SW3按键在按下松开后吗,触发此中断函数,修改kbi_stat值,来模拟鼠标右击功能。
void IRQ_ISR_PORTA(void)
{
#if defined(MCU_MK20D5)
NVICICPR1 = 1 << ((40)%32);
NVICISER1 = 1 << ((40)%32);
#elif defined (MCU_MKL25Z4)
NVIC_ICPR = 1 << 30;
NVIC_ISER = 1 << 30;
#else
NVICICPR2 = 1 << ((87)%32);
NVICISER2 = 1 << ((87)%32);
#endif
DisableInterrupts;
#if defined MCU_MKL25Z4
if(PORTA_ISFR & (1<<4))
{
kbi_stat |= 0x02; /* Update the kbi state */
PORTA_ISFR = (1 << 4); /* Clear the bit by writing a 1 to it */
}
#else
if(PORTA_ISFR & (1<<19))
{
kbi_stat |= 0x02; /* Update the kbi state */
PORTA_ISFR = (1 << 19); /* Clear the bit by writing a 1 to it */
}
#endif
EnableInterrupts;
}
USB_Class_HID_Send_Data() USB_Class_HID_Send_Data()实现将报告描述符定义的4个字节的报告数据返回给HOST PC。
******************************************************************************
* This function is used by Application to send data through HID class
*****************************************************************************/
uint_8 USB_Class_HID_Send_Data (
uint_8 controller_ID, /* [IN] Controller ID */
uint_8 ep_num, /* [IN] Endpoint Number */
uint_8_ptr app_buff, /* [IN] Buffer to Send */
USB_PACKET_SIZE size /* [IN] Length of the Transfer */
)
{
uint_8 index;
//volatile uint_8 producer, consumer;
uint_8 producer, consumer;
uint_8 status = USB_OK;
USB_ENDPOINTS *ep_desc_data = (USB_ENDPOINTS *)
USB_Desc_Get_Endpoints(controller_ID);
DisableInterrupts;
/* map the endpoint num to the index of the endpoint structure */
index = USB_Map_Ep_To_Struct_Index(controller_ID, ep_num);
producer = g_hid_endpoint_data.ep[index].bin_producer;
consumer = g_hid_endpoint_data.ep[index].bin_consumer;
if((uint_8)(producer - consumer) != (uint_8)(MAX_QUEUE_ELEMS))
{
/* the bin is not full*/
uint_8 queue_num = (uint_8)(producer % MAX_QUEUE_ELEMS);
/* queue the send request */
/* put all send request parameters in the endpoint data structure */
g_hid_endpoint_data.ep[index].queue[queue_num].controller_ID =
controller_ID;
g_hid_endpoint_data.ep[index].queue[queue_num].channel = ep_num;
g_hid_endpoint_data.ep[index].queue[queue_num].app_buff = app_buff;
g_hid_endpoint_data.ep[index].queue[queue_num].size = size;
/* increment producer bin by 1*/
g_hid_endpoint_data.ep[index].bin_producer++;
producer++;
if((uint_8)(producer - consumer) == (uint_8)1)
{
/* send the IO if there is only one element in the queue */
status = USB_Class_Send_Data(controller_ID, ep_num, app_buff,size);
}
}
else /* bin is full */
{
status = USBERR_DEVICE_BUSY;
}
EnableInterrupts;
return status;
}
3. 例程调试 运行平台 1.TWR-KL25Z48M
2.CW10.6 运行例程(CW)
1) 使用USB cable连接TWR-KL25Z48M开发板Min-B USB连接器(J23);
2) 加载工程后,点击
进行编译;
3) 编译成功后,点击
进入调试界面;
4) 进入调试界面后,使用USB cable连接-KL25Z48M开发板micro USB连接器(J13),接着点击运行例程。 平台搭建
图 1 TWRKL25Z48M开发板
USB分析仪监测·
1.枚举过程数据包分析
枚举过程的数据包分析,已在《USBHID设备应用(进阶篇)》中进行过详细介绍,在此就不重复介绍了,大家可以到论坛去下载《USB HID设备应用(进阶篇)》文档。
2. 报告数据分析
|