/**HEADER********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: mouse.c$
* $Version : 3.6.4.0$
* $Date    : Jun-4-2010$
*
* Comments:
*
* @brief  The file emulates a mouse cursor movements
*
*****************************************************************************/

/******************************************************************************
 * Includes
 *****************************************************************************/
#include "mouse.h"
#include <usb_hid.h>
#include "demo.h"

void USB_Mouse_Init(void);

/****************************************************************************
 * Global Variables
 ****************************************************************************/
/* Add all the variables needed for mouse.c to this structure */
extern USB_ENDPOINTS usb_desc_ep;
extern DESC_CALLBACK_FUNCTIONS_STRUCT  desc_callback;
MOUSE_GLOBAL_VARIABLE_STRUCT g_mouse;

/*****************************************************************************
 * Local Types - None
 *****************************************************************************/

/*****************************************************************************
 * Local Functions Prototypes
 *****************************************************************************/
void USB_App_Callback(uint_8 event_type, void* val,pointer arg);
uint_8 USB_App_Param_Callback(uint_8 request, uint_16 value, uint_8_ptr* data,
    uint_32* size,pointer arg);

signed char MouseX();
signed char MouseY();
/*****************************************************************************
 * Local Variables
 *****************************************************************************/

/*****************************************************************************
 * Local Functions
 *****************************************************************************/

/*****************************************************************************
*
*      @name     move_mouse
*
*      @brief    This function gets makes the cursor on screen move left,right
*                up and down
*
*      @param    None
*
*      @return   None
*
*
******************************************************************************/
void move_mouse(void)
{
  g_mouse.rpt_buf[1]=(unsigned char)MouseX();
  g_mouse.rpt_buf[2]=(unsigned char)MouseY();
  if(GetInput(SW2_INPUT)) //Left click
  {
    g_mouse.rpt_buf[0] = 1;
  }
  else if(GetInput(SW1_INPUT)) //Right click
  {
    g_mouse.rpt_buf[0] = 2;
  }
  else //no click
  {
    g_mouse.rpt_buf[0] = 0;
  }

    (void)USB_Class_HID_Send_Data(g_mouse.app_handle,HID_ENDPOINT,
        g_mouse.rpt_buf,MOUSE_BUFF_SIZE);


}


/*******************************************************************/
/*!
 * Detect tilting in the X-direction to move mouse
 */
signed char MouseX()
{
  signed char x_output;
  /* If tilting far right move mouse fast to right */
  if(Sensor.accel_x<-15)
  {
    x_output=-4;
  }
  /* If tilting slightly right move mouse slowly to right */
  else if(Sensor.accel_x<-7)
  {
      x_output=-1;
  }
  /* If tilting far left move mouse fast to left */
  else if(Sensor.accel_x>15)
  {
     x_output=4;
  }
  /* If tilting slightly left move mouse slowly to left */
  else if(Sensor.accel_x>7)
  {
     x_output=1;
  }
  /* If not tilting than don't move mouse */
  else
  {
    x_output=0;
  }
  return x_output;
}

/*******************************************************************/
/*!
 * Detect tilting in the Y-direction to move mouse
 */
signed char MouseY()
{
  signed char y_output;
  /* If tilting far up, move mouse fast up */
  if(Sensor.accel_y<-15)
  {
    y_output=8;
  }
  /* If tilting slightly up, move mouse slowly up */
  else if(Sensor.accel_y<-7)
  {
    y_output=1;
  }
  /* If tilting far down, move mouse fast down */
  else if(Sensor.accel_y>15)
  {
     y_output=-8;
  }
  /* If tilting slightly down, move mouse slowly down */
  else if(Sensor.accel_y>7)
  {
     y_output=-1;
  }
  /* If not tilting than don't move mouse */
  else
  {
    y_output=0;
  }
  return y_output;
}


/******************************************************************************
 *
 *    @name        USB_App_Callback
 *
 *    @brief       This function handles the callback
 *
 *    @param       handle : handle to Identify the controller
 *    @param       event_type : value of the event
 *    @param       val : gives the configuration value
 *
 *    @return      None
 *
 *****************************************************************************/
void USB_App_Callback(uint_8 event_type, void* val,pointer arg)
{
    UNUSED_ARGUMENT (arg)
    UNUSED_ARGUMENT (val)

    switch(event_type)
    {
        case USB_APP_BUS_RESET:
            g_mouse.mouse_init=FALSE;
            break;
        case USB_APP_ENUM_COMPLETE:
            g_mouse.mouse_init = TRUE;
            move_mouse();/* run the coursor movement code */
            break;
        case USB_APP_SEND_COMPLETE:
             /*check whether enumeration is complete or not */
            if(g_mouse.mouse_init)
            {
                #if COMPLIANCE_TESTING
                    uint_32 g_compliance_delay = 0x009FFFFF;
                    while(g_compliance_delay--);
                #endif
                move_mouse();/* run the coursor movement code */
            }
            break;
        case USB_APP_ERROR:
            /* user may add code here for error handling
               NOTE : val has the value of error from h/w*/
            break;
        default:
            break;
    }
    return;
}

/******************************************************************************
 *
 *    @name        USB_App_Param_Callback
 *
 *    @brief       This function handles the callback for Get/Set report req
 *
 *    @param       request  :  request type
 *    @param       value    :  give report type and id
 *    @param       data     :  pointer to the data
 *    @param       size     :  size of the transfer
 *
 *    @return      status
 *                  USB_OK  :  if successful
 *                  else return error
 *
 *****************************************************************************/
 uint_8 USB_App_Param_Callback
 (
    uint_8 request,
    uint_16 value,
    uint_8_ptr* data,
    uint_32* size,
    pointer arg
)
{
    uint_8 error = USB_OK;
    uint_8 index = (uint_8)((request - 2) & USB_HID_REQUEST_TYPE_MASK);

    UNUSED_ARGUMENT(arg)
    /* index == 0 for get/set idle, index == 1 for get/set protocol */
    *size = 0;
    /* handle the class request */
    switch(request)
    {
        case USB_HID_GET_REPORT_REQUEST :
            *data = &g_mouse.rpt_buf[0]; /* point to the report to send */
            *size = MOUSE_BUFF_SIZE; /* report size */
            break;

        case USB_HID_SET_REPORT_REQUEST :
            for(index = 0; index < MOUSE_BUFF_SIZE ; index++)
            {   /* copy the report sent by the host */
                g_mouse.rpt_buf[index] = *(*data + index);
            }
            break;

        case USB_HID_GET_IDLE_REQUEST :
            /* point to the current idle rate */
            *data = &g_mouse.app_request_params[index];
            *size = REQ_DATA_SIZE;
            break;

        case USB_HID_SET_IDLE_REQUEST :
            /* set the idle rate sent by the host */
            g_mouse.app_request_params[index] =(uint_8)((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_mouse.app_request_params[index];
            *size = REQ_DATA_SIZE;
            break;

        case USB_HID_SET_PROTOCOL_REQUEST :
            /* set the protocol sent by the host
               0 = Boot Protocol
               1 = Report Protocol*/
               g_mouse.app_request_params[index] = (uint_8)(value);
               break;
    }
    return error;
}

/******************************************************************************
 *
 *   @name        TestApp_Init
 *
 *   @brief       This function is the entry for mouse (or other usuage)
 *
 *   @param       None
 *
 *   @return      None
 **
 *****************************************************************************/
void USB_Mouse_Init(void)
{
    HID_CONFIG_STRUCT   config_struct;

    _int_disable();
    /* initialize the Global Variable Structure */
    USB_mem_zero(&g_mouse, sizeof(MOUSE_GLOBAL_VARIABLE_STRUCT));
    USB_mem_zero(&config_struct, sizeof(HID_CONFIG_STRUCT));
    /* Initialize the USB interface */

    config_struct.ep_desc_data = &usb_desc_ep;
    config_struct.hid_class_callback.callback =USB_App_Callback;
    config_struct.hid_class_callback.arg = &g_mouse.app_handle;
    config_struct.param_callback.callback =USB_App_Param_Callback;
    config_struct.param_callback.arg = &g_mouse.app_handle;
    config_struct.desc_callback_ptr = &desc_callback;
    config_struct.desc_endpoint_cnt = HID_DESC_ENDPOINT_COUNT;
    config_struct.ep = g_mouse.ep;

    g_mouse.app_handle = USB_Class_HID_Init(&config_struct);
    _int_enable();
    while (TRUE)
    {
        _task_block();
        /* call the periodic task function */
        USB_HID_Periodic_Task();
    }

}

/*FUNCTION*----------------------------------------------------------------
*
* Function Name  : Main_Task
* Returned Value : None
* Comments       :
*     First function called.  Calls Test_App
*     callback functions.
*
*END*--------------------------------------------------------------------*/
void usb_task(uint_32 param )
{
  printf("Starting USB Task\n");
  USB_Mouse_Init();
}

/* EOF */