打印
[资料分享与下载]

[经验分享]鼠标HID例程简析(下)

[复制链接]
2213|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
HID, se, ic, ST, TE
本帖最后由 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. 报告数据分析

文档完整: 鼠标HID例程(下).pdf (540.38 KB)
参考文献:[1] Freescale USB DeviceStack Users Guide
                [2] Freescale USB StackDevice API Reference Manual
                [3] FSL USB Stack v4.1.1

8.jpg (889 Bytes )

8.jpg

相关帖子

沙发
FSL_TICS_Jeremy|  楼主 | 2014-9-18 17:06 | 只看该作者
如有什么错误或者不足,欢迎网友指正,请在后面跟帖!

使用特权

评论回复
板凳
qq4988| | 2014-9-18 17:09 | 只看该作者
谢谢版主分享啊

使用特权

评论回复
地板
haolaishi| | 2014-12-28 15:53 | 只看该作者
学习了

使用特权

评论回复
5
deliciouscook| | 2015-1-25 19:37 | 只看该作者
学习学习

使用特权

评论回复
6
deliciouscook| | 2015-1-25 19:37 | 只看该作者
学习学习

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

113

主题

2865

帖子

38

粉丝