FSL_TICS_ZP 发表于 2014-9-18 16:11:36

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

鼠标HID例程简析
   前两天已经陆续分享了两篇帖子来介绍鼠标HID例程,今天再接再励继续扫尾工作。闲话少叙,马上开整。
   TestApp_Init()
   在TestApp_Init()函数内,通过Emulate_Mouse_WithButton()函数来模拟鼠标各式功能:左击、右击,上移、下移,左移、右移,而其中的USB_Class_HID_Send_Data()函数用于实现中断端点与HostPC进行数据通信。
*****************************************************************************
* 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按键进行操作,而实现以上功能的关键就是:需要网友朋友们在理解鼠标报表描述符的基础上修改数据,并将其传递给中断端点。对报表描述符的介绍就不在本文展开啊,不了解的网友可以去参考先前分享的《USB HID设备应用(进阶篇)》一文。
*****************************************************************************
* 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 = LEFT_CLICK;
               rpt_buf = 0x00;
               rpt_buf = 0x00;
               break;

         case RIGHT_CLICK : /* PTG1 (right click)   is pressed */
               rpt_buf = RIGHT_CLICK;
               rpt_buf = 0x00;
               rpt_buf = 0x00;

               break;

         case MOVE_LEFT_RIGHT :/* PTG2 (left
                                    or right movement--depends on
                                    UP_LEFT macro) is pressed*/
               rpt_buf = SHIFT_VAL;
               rpt_buf = 0x00;
               rpt_buf = 0x00;
               break;

         case MOVE_UP_DOWN :          /* PTG3 (up or down
                                          movement--depends on
                                          UP_LEFT macro) is pressed*/
               rpt_buf = SHIFT_VAL;
               rpt_buf = 0x00;
               rpt_buf = 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)
      {
            /* 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,       /* Controller ID */
    uint_8 ep_num,            /* Endpoint Number */
    uint_8_ptr app_buff,      /* Buffer to Send */
    USB_PACKET_SIZE size      /* 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.bin_producer;
    consumer = g_hid_endpoint_data.ep.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.queue.controller_ID =
            controller_ID;
      g_hid_endpoint_data.ep.queue.channel = ep_num;
      g_hid_endpoint_data.ep.queue.app_buff = app_buff;
      g_hid_endpoint_data.ep.queue.size = size;

      /* increment producer bin by 1*/
      g_hid_endpoint_data.ep.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分析仪监测
•        枚举过程数据包分析
       枚举过程的数据包分析,已在《USB HID设备应用(进阶篇)》中进行过详细介绍,在此就不重复介绍了,大家可以到论坛去下载《USB HID设备应用(进阶篇)》文档。
•        报告数据分析

文档下载:
参考文献:
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 16:13:08

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

子鱼 发表于 2014-9-18 16:26:53

可以把‘鼠标HID例程简析(上)’的帖子链接加上

shian0551 发表于 2014-9-18 17:16:08

找不到 鼠标HID例程简析(上)的帖子 啊..麻烦楼主加上啊.

FSL_TICS_ZP 发表于 2014-9-18 17:17:46

子鱼 发表于 2014-9-18 16:26
可以把‘鼠标HID例程简析(上)’的帖子链接加上

从这个链接可以找到所有三篇文章的链接。
http://www.amobbs.com/thread-5578500-1-1.html

FSL_TICS_ZP 发表于 2014-9-18 17:34:30

shian0551 发表于 2014-9-18 17:16
找不到 鼠标HID例程简析(上)的帖子 啊..麻烦楼主加上啊.

从这个链接可以找到所有三篇文章的链接。
http://www.amobbs.com/thread-5578500-1-1.html
页: [1]
查看完整版本: 【经验分享】鼠标HID例程简析(下)