| /*******************************************************************************
|
|
|
| This software file (the "File") is distributed by Marvell International Ltd.
|
| or its affiliate(s) under the terms of the GNU General Public License Version 2,
|
| June 1991 (the "License"). You may use, redistribute and/or modify this File
|
| in accordance with the terms and conditions of the License, a copy of which
|
| is available along with the File in the license.txt file or by writing to the
|
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
| or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
|
|
|
| THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
|
| WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
|
| DISCLAIMED. The GPL License provides additional details about this warranty
|
| disclaimer.
|
|
|
| (C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved.
|
| (C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved.
|
|
|
| *******************************************************************************/
|
| |
| /************************************************************************** |
| Include the USB stack header files. |
| **************************************************************************/ |
| #include "usb/api/mvUsbDefs.h" |
| #include "usb/api/mvUsbDebug.h" |
| #include "usb/api/mvUsbCh9.h" |
| #include "usb/api/mvUsbDevApi.h" |
| |
| #include "usb/examples/mouse.h" |
| |
| /************************************************************************** |
| global variables and some defines for device. |
| **************************************************************************/ |
| |
| #define CONTROL_MAX_PACKET_SIZE (64) |
| #define INTERRUPT_MAX_PACKET_SIZE (0x0008) |
| #define DEV_DESC_MAX_PACKET_SIZE (7) |
| #define INTERRUPT_EP (1) |
| #define FRAME_INTERVAL (15) |
| |
| /************************************************************************** |
| Include the OS and BSP dependent files that define IO functions and |
| basic types. You may like to change these files for your board and RTOS |
| **************************************************************************/ |
| |
| int frame_interval = FRAME_INTERVAL; |
| int mouseCntr = 0; |
| int mouseDelay = 2; |
| |
| static volatile boolean TEST_ENABLED = FALSE; |
| static volatile boolean USB_SUSPENDED = FALSE; |
| |
| #define EP1_RECV_BUFFER_SIZE 10 |
| static uint_8_ptr hid_test_rep_data; |
| static uint_8_ptr hid_test_rep_data_unaligned; |
| |
| /******************************** |
| Buffers for sending data to stack |
| ********************************/ |
| #define EP0_SEND_BUFFER_SIZE 200 |
| static uint_8_ptr Send_Buffer_Unaligned; |
| static uint_8_ptr Send_Buffer_aligned; |
| |
| static uint_8 data_to_send; |
| static uint_16 sof_count; |
| static SETUP_STRUCT local_setup_packet; |
| |
| |
| /************************************************************************* |
| Device descriptors are always 18 bytes |
| |
| Offset| Field | Value | Description |
| ------|--------------------|-------|-------------------- |
| 0 | bLength | 0x12 |The size of this |
| | | |descriptor is 18 bytes |
| ------|--------------------|-------|-------------------- |
| 1 | bDescriptorType | 0x01 |DEVICE Descriptor Type |
| ------|--------------------|-------|-------------------- |
| 2 | bcdUSB | 0x0100|Device compliant to |
| | | |the USB |
| | | |specification |
| | | |version 1.00 |
| ------|--------------------|-------|-------------------- |
| 4 | bDeviceClass | 0x00 |Each interface |
| | | |specifies its own |
| | | |class information |
| ------|--------------------|-------|-------------------- |
| 5 | bDeviceSubClass | 0x00 |Each interface |
| | | |specifies its own |
| | | |subclass information |
| ------|--------------------|-------|-------------------- |
| 6 | bDeviceProtocol | 0x00 |No protocols on the |
| | | |device basis |
| ------|--------------------|-------|-------------------- |
| 7 | bMaxPacketSize0 | 0x08 |Maximum packet size |
| | | |for endpoint zero is 8 |
| ------|--------------------|-------|-------------------- |
| 8 | idVendor | 0x0261|Vendor ID is 609: |
| | | |
| ------|--------------------|-------|-------------------- |
| 10 | idProduct | 0x4D03|The Product ID is 0x4D03 |
| ------|--------------------|-------|-------------------- |
| 12 | bcdDevice | 0x0441|The device release |
| | | |number is 4.41 |
| ------|--------------------|-------|-------------------- |
| 14 | iManufacturer | 0x00 |The device doesn't |
| | | |have the string |
| | | |descriptor |
| | | |describing the manufacturer |
| ------|--------------------|-------|-------------------- |
| 15 | iProduct | 0x00 |The device doesn't |
| | | |have the string |
| | | |descriptor |
| | | |describing the product |
| ------|--------------------|-------|-------------------- |
| 16 | iSerialNumber | 0x00 | |
| ------|--------------------|-------|-------------------- |
| 17 | bNumConfigurations | 0x01 | |
| ------|--------------------|-------|-------------------- |
| *************************************************************************/ |
| #define DEVICE_DESCRIPTOR_SIZE 18 |
| static uint_8_ptr DevDesc; |
| static uint_8 DevDescData[DEVICE_DESCRIPTOR_SIZE] = |
| { |
| DEVICE_DESCRIPTOR_SIZE, |
| 0x01, |
| 0x0,2, |
| |
| 0x00, |
| 0x00, |
| 0x00, |
| CONTROL_MAX_PACKET_SIZE, |
| /* Vendor ID = MARVELL */ |
| USB_uint_16_low(0x1286), USB_uint_16_high(0x1286), |
| /* Product ID */ |
| USB_uint_16_low(0x1), USB_uint_16_high(0x1), |
| /* BCD Device version */ |
| USB_uint_16_low(0x0002), USB_uint_16_high(0x0002), |
| |
| 0x01, /* iManufacturer */ |
| 0x02, /* iProduct */ |
| 0x00, /* iSerialNumber */ |
| 0x01 /* bNumConfigurations */ |
| |
| }; |
| |
| /* USB 2.0 specific descriptor */ |
| #define DEVICE_QUALIFIER_DESCRIPTOR_SIZE 10 |
| static uint_8_ptr DevQualifierDesc; |
| static uint_8 DevQualifierDescData[DEVICE_QUALIFIER_DESCRIPTOR_SIZE] = |
| { |
| DEVICE_QUALIFIER_DESCRIPTOR_SIZE, /* bLength Length of this descriptor */ |
| 6, /* bDescType This is a DEVICE Qualifier descr */ |
| 0,2, /* bcdUSB USB revision 2.0 */ |
| 0, /* bDeviceClass */ |
| 0, /* bDeviceSubClass */ |
| 0, /* bDeviceProtocol */ |
| CONTROL_MAX_PACKET_SIZE, /* bMaxPacketSize0 */ |
| 0x01, /* bNumConfigurations */ |
| 0 |
| }; |
| |
| |
| /******************************************************************* |
| CONFIG DESCRIPTOR |
| |
| Data stage (34 bytes) : |
| ------------------------------------ |
| |
| CONFIGURATION Descriptor |
| ------------------------ |
| Offset| Field | Value | Description |
| ------|---------------------|-------|-------------------- |
| 0 | bLength | 0x09 |The size of this |
| | | |descriptor is 9 bytes |
| ------|---------------------|-------|-------------------- |
| 1 | bDescriptorType | 0x02 |CONFIGURATION |
| | | |Descriptor Type |
| ------|---------------------|-------|-------------------- |
| 2 | wTotalLength | 0x0022|The total length of |
| | | |data for this |
| | | |configuration is 34. |
| | | |This includes the |
| | | |combined length of |
| | | |all the descriptors returned |
| ------|---------------------|-------|-------------------- |
| 4 | bNumInterfaces | 0x01 |This configuration |
| | | |supports 1 interfaces |
| ------|---------------------|-------|-------------------- |
| 5 | bConfigurationValue | 0x01 |The value 1 should |
| | | |be used to select |
| | | |this configuration |
| ------|---------------------|-------|-------------------- |
| 6 | iConfiguration | 0x00 |The device doesn't |
| | | |have the string |
| | | |descriptor |
| | | |describing this configuration |
| ------|---------------------|-------|-------------------- |
| 7 | bmAttributes | 0x80 |Configuration characteristics : |
| | | |Bit 7: Reserved (set to one) 1 |
| | | |Bit 6: Self-powered 0 |
| | | |Bit 5: Remote Wakeup 1 |
| ------|---------------------|-------|-------------------- |
| 8 | MaxPower | 0x32 |Maximum power |
| | | |consumption of the |
| | | |device in this |
| | | |configuration is 100 mA |
| ------|---------------------|-------|-------------------- |
| |
| INTERFACE Descriptor |
| -------------------- |
| Offset| Field | Value | Description |
| ------|--------------------|-------|-------------------- |
| 0 | bLength | 0x09 |The size of this |
| | | |descriptor is 9 bytes |
| ------|--------------------|-------|-------------------- |
| 1 | bDescriptorType | 0x04 |INTERFACE Descriptor Type |
| ------|--------------------|-------|-------------------- |
| 2 | bInterfaceNumber | 0x00 |The number of this |
| | | |interface is 0 |
| ------|--------------------|-------|-------------------- |
| 3 | bAlternateSetting | 0x00 |The value used to |
| | | |select alternate |
| | | |setting for this |
| | | |interface is 0 |
| ------|--------------------|-------|-------------------- |
| 4 | bNumEndpoints | 0x01 |The number of |
| | | |endpoints used by |
| | | |this interface is 1 |
| | | |(excluding endpoint zero) |
| ------|--------------------|-------|-------------------- |
| 5 | bInterfaceClass | 0x03 |The interface |
| | | |implements HID class |
| ------|--------------------|-------|-------------------- |
| 6 | bInterfaceSubClass | 0x01 |The subclass code is 0x01 |
| ------|--------------------|-------|-------------------- |
| 7 | bInterfaceProtocol | 0x02 |The protocol code is 0x02 |
| ------|--------------------|-------|-------------------- |
| 8 | iInterface | 0x00 |The device doesn't |
| | | |have the string |
| | | |descriptor |
| | | |describing this interface |
| ------|--------------------|-------|-------------------- |
| |
| HID Descriptor |
| -------------- |
| Offset| Field | Value | Description |
| ------|-------------------|-------|-------------------- |
| 0 | bLength | 0x09 |The size of this |
| | | |descriptor is 9 bytes |
| ------|-------------------|-------|-------------------- |
| 1 | bDescriptorType | 0x21 |HID Descriptor Type |
| ------|-------------------|-------|-------------------- |
| 2 | bcdHID | 0x0100|Device compliant to |
| | | |the HID |
| | | |specification |
| | | |version 1.00 |
| ------|-------------------|-------|-------------------- |
| 4 | bCountryCode | 0x00 |The country code is 0x00 |
| ------|-------------------|-------|-------------------- |
| 5 | bNumDescriptors | 0x01 |The number of class |
| | | |descriptors is 1 |
| ------|-------------------|-------|-------------------- |
| 6 | bDescriptorType | 0x22 |The class descriptor |
| | | |is Report descriptor |
| ------|-------------------|-------|-------------------- |
| 7 | wDescriptorlength | 0x0034|The total size of |
| | | |the class descriptor |
| | | |is 52 |
| ------|-------------------|-------|-------------------- |
| |
| ENDPOINT Descriptor |
| ------------------- |
| Offset| Field | Value | Description |
| ------|------------------|-------|-------------------- |
| 0 | bLength | 0x07 |The size of this |
| | | |descriptor is 7 bytes |
| ------|------------------|-------|-------------------- |
| 1 | bDescriptorType | 0x05 |ENDPOINT Descriptor Type |
| ------|------------------|-------|-------------------- |
| 2 | bEndpointAddress | 0x81 |This is an IN |
| | | |endpoint with |
| | | |address (endpoint |
| | | |number) 1 |
| ------|------------------|-------|-------------------- |
| 3 | bmAttributes | 0x03 |Types - |
| | | |Transfer:INTERRUPT |
| | | |Sync:No Sync |
| | | |Usage:Data EP |
| ------|------------------|-------|-------------------- |
| 4 | wMaxPacketSize | 0x0004|Maximum packet size |
| | | |value for this |
| | | |endpoint is 0x4 |
| | | |(Bits 12-11: Addtl. Transactions/frame) |
| ------|------------------|-------|-------------------- |
| 6 | bInterval | 0x0A |bInterval:10. The |
| | | |polling interval |
| | | |value is bInterval |
| | | |or 2**(bInterval-1) |
| ------|------------------|-------|-------------------- |
| |
| *******************************************************************/ |
| |
| |
| #define CONFIG_DESC_NUM_INTERFACES (4) |
| |
| /* This must be counted manually and updated with the descriptor */ |
| /* 1*Config(9) + 1*Interface(9) + 1*HID(9) + 1* Endpoint (7)= 34 bytes */ |
| #define CONFIG_DESC_SIZE (34) |
| |
| static uint_8_ptr ConfigDesc; |
| |
| static uint_8 ConfigDescData[CONFIG_DESC_SIZE] = |
| { |
| /*Config Descriptor */ |
| 0x09, |
| 0x02, |
| USB_uint_16_low(CONFIG_DESC_SIZE), |
| USB_uint_16_high(CONFIG_DESC_SIZE), |
| 0x01, |
| 0x01, |
| 0x00, |
| 0xE0, /* 0x80, */ |
| 0x0, |
| /* Interface Descriptor */ |
| 0x09, |
| 0x04, |
| 0x00, |
| 0x00, |
| 0x01, |
| 0x03, |
| 0x01, |
| 0x02, |
| 0x00, |
| |
| /* HID descriptor */ |
| 0x09, |
| 0x21, |
| USB_uint_16_low(0x0100), |
| USB_uint_16_high(0x0100), |
| 0x00, |
| 0x01, |
| 0x22, |
| USB_uint_16_low(0x0034), |
| USB_uint_16_high(0x0034), |
| |
| /*Endpoint descriptor */ |
| 0x07, |
| 0x05, |
| (0x80+INTERRUPT_EP), |
| 0x03, |
| USB_uint_16_low(INTERRUPT_MAX_PACKET_SIZE), |
| USB_uint_16_high(INTERRUPT_MAX_PACKET_SIZE), |
| FRAME_INTERVAL |
| }; |
| |
| #define OTHER_SPEED_CONFIG_DESC_SIZE CONFIG_DESC_SIZE |
| static uint_8_ptr other_speed_config; |
| static uint_8 other_speed_config_data[CONFIG_DESC_SIZE] = |
| { |
| /*Config Descriptor */ |
| 0x09, |
| 0x07, |
| USB_uint_16_low(CONFIG_DESC_SIZE), |
| USB_uint_16_high(CONFIG_DESC_SIZE), |
| 0x01, |
| 0x01, |
| 0x00, |
| 0xE0, /* 0x80, */ |
| 0x0, |
| /* Interface Descriptor */ |
| 0x09, |
| 0x04, |
| 0x00, |
| 0x00, |
| 0x01, |
| 0x03, |
| 0x01, |
| 0x02, |
| 0x00, |
| |
| /* HID descriptor */ |
| 0x09, |
| 0x21, |
| USB_uint_16_low(0x0100), |
| USB_uint_16_high(0x0100), |
| 0x00, |
| 0x01, |
| 0x22, |
| USB_uint_16_low(0x0034), |
| USB_uint_16_high(0x0034), |
| |
| /*Endpoint descriptor */ |
| 0x07, |
| 0x05, |
| (0x80+INTERRUPT_EP), |
| 0x03, |
| USB_uint_16_low(INTERRUPT_MAX_PACKET_SIZE), |
| USB_uint_16_high(INTERRUPT_MAX_PACKET_SIZE), |
| FRAME_INTERVAL |
| |
| }; |
| /************************************************************************ |
| |
| HID Class Report Descriptor : |
| |
| Item Value(Hex) |
| ------------------------------------------------------------------------------------------------------------ |
| Usage Page (Generic Desktop Control) 05 01 |
| Usage (Mouse) 09 02 |
| Collection (Application) A1 01 |
| Usage (Pointer) 09 01 |
| Collection (Physical) A1 00 |
| Usage Page (Button) 05 09 |
| Usage Minimum (1) 19 01 |
| Usage Maximum (3) 29 03 |
| Logical Minimum (0) 15 00 |
| Logical Maximum (1) 25 01 |
| Report Count (3) 95 03 |
| Report Size (1) 75 01 |
| Input (Data, Variable, Absolute) 81 02 |
| Report Count (1) 95 01 |
| Report Size (5) 75 05 |
| Input (Constant) 81 01 |
| Usage Page (Generic Desktop Control) 05 01 |
| Usage (X) 09 30 |
| Usage (Y) 09 31 |
| Usage (Wheel) 09 38 |
| Logical Minimum (-127) 15 81 |
| Logical Maximum (127) 25 7F |
| Report Size (8) 75 08 |
| Report Count (3) 95 03 |
| Input (Data, Variable, Relative) 81 06 |
| End Collection C0 |
| End Collection C0 |
| |
| |
| ************************************************************************/ |
| |
| #define REPORT_DESC_SIZE (52) |
| static uint_8_ptr ReportDesc; |
| |
| static uint_8 ReportDescData[REPORT_DESC_SIZE] = |
| { |
| 0x05, |
| 0x01, |
| 0x09, |
| 0x02, |
| 0xA1, |
| 0x01, |
| 0x09, |
| 0x01, |
| |
| 0xA1, |
| 0x00, |
| 0x05, |
| 0x09, |
| 0x19, |
| 0x01, |
| 0x29, |
| 0x03, |
| |
| 0x15, |
| 0x00, |
| 0x25, |
| 0x01, |
| 0x95, |
| 0x03, |
| 0x75, |
| 0x01, |
| |
| 0x81, |
| 0x02, |
| 0x95, |
| 0x01, |
| 0x75, |
| 0x05, |
| 0x81, |
| 0x01, |
| |
| 0x05, |
| 0x01, |
| 0x09, |
| 0x30, |
| 0x09, |
| 0x31, |
| 0x09, |
| 0x38, |
| |
| 0x15, |
| 0x81, |
| 0x25, |
| 0x7F, |
| 0x75, |
| 0x08, |
| 0x95, |
| 0x03, |
| |
| 0x81, |
| 0x06, |
| 0xC0, |
| 0xC0 |
| }; |
| |
| /************************************************************** |
| This report descriptor can be used to report the set_report |
| and get_report capability to host. When this is used, modify |
| the config descriptor to reflect the size of report descriptor. |
| The following lines should be changed, |
| |
| USB_uint_16_low(0x0038), // Changed from USB_uint_16_low(0x0034), |
| USB_uint_16_high(0x0038), // Changed from USB_uint_16_high(0x0034), |
| |
| |
| |
| |
| uint_8 ReportDesc[56] = { |
| 0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop) |
| 0x09, 0x01, // USAGE (Vendor Usage 1) |
| 0xa1, 0x01, // COLLECTION (Application) |
| |
| 0x09, 0x02, // USAGE (Vendor Usage 2) |
| 0x15, 0x80, // LOGICAL_MINIMUM (-128) |
| 0x25, 0x7f, // LOGICAL_MAXIMUM (127) |
| 0x95, 0x01, // REPORT_COUNT (1) |
| 0x75, 0x08, // REPORT_SIZE (8) |
| 0xb1, 0x02, // FEATURE (Data,Var,Abs) |
| |
| 0x09, 0x03, // USAGE (Vendor Usage 3) |
| 0x15, 0x80, // LOGICAL_MINIMUM (-128) |
| 0x25, 0x7f, // LOGICAL_MAXIMUM (127) |
| 0x95, 0x01, // REPORT_COUNT (1) |
| 0x75, 0x08, // REPORT_SIZE (8) |
| 0xb1, 0x02, // FEATURE (Data,Var,Abs) |
| |
| 0x09, 0x04, // USAGE (Vendor Usage 4) |
| 0x15, 0x80, // LOGICAL_MINIMUM (-128) |
| 0x25, 0x7f, // LOGICAL_MAXIMUM (127) |
| 0x95, 0x01, // REPORT_COUNT (1) |
| 0x75, 0x08, // REPORT_SIZE (8) |
| 0xb1, 0x02, // FEATURE (Data,Var,Abs) |
| |
| 0x09, 0x05, // USAGE (Vendor Usage 5) |
| 0x15, 0x80, // LOGICAL_MINIMUM (-128) |
| 0x25, 0x7f, // LOGICAL_MAXIMUM (127) |
| 0x95, 0x01, // REPORT_COUNT (1) |
| 0x75, 0x08, // REPORT_SIZE (8) |
| 0xb1, 0x02, // FEATURE (Data,Var,Abs) |
| |
| 0xc0 // END_COLLECTION |
| }; |
| ***************************************************************/ |
| |
| /********************************************************************** |
| Mouse data (this structure is used to send mouse movement information) |
| **********************************************************************/ |
| typedef struct _MOUSE_DATA { |
| char a; |
| char b; |
| char c; |
| char d; |
| |
| } MOUSE_DATA_STRUCT; |
| |
| static MOUSE_DATA_STRUCT mouse_data = {0,0,0,0}; |
| |
| static uint_8 USB_IF_ALT[4] = { 0, 0, 0, 0}; |
| |
| /* number of strings in the table not including 0 or n. */ |
| static const uint_8 USB_STR_NUM = 6; |
| |
| /* |
| ** if the number of strings changes, look for USB_STR_0 everywhere and make |
| ** the obvious changes. It should be found in 3 places. |
| */ |
| |
| static const uint_16 USB_STR_0[ 2] = {0x0300 + sizeof(USB_STR_0),0x0409}; |
| static const uint_16 USB_STR_1[26] = {0x0300 + sizeof(USB_STR_1), |
| 'M','a','r','v','e','l','l',' ','S','e','m','i','c','o','n','d','u','c','t','o','r',' ','L','t','d'}; |
| static const uint_16 USB_STR_2[28] = {0x0300 + sizeof(USB_STR_2), |
| 'M','A','R','V','E','L','L',' ','U','S','B',' ','h','i','d','m','o','u','s','e',' ',\ |
| 'D','e','v','i','c','e'}; |
| static const uint_16 USB_STR_3[ 5] = {0x0300 + sizeof(USB_STR_3), |
| 'B','E','T','A'}; |
| static const uint_16 USB_STR_4[ 4] = {0x0300 + sizeof(USB_STR_4), |
| '#','0','2'}; |
| static const uint_16 USB_STR_5[ 4] = {0x0300 + sizeof(USB_STR_5), |
| '_','A','1'}; |
| static const uint_16 USB_STR_6[15] = {0x0300 + sizeof(USB_STR_6), |
| 'Y','o','u','r',' ','n','a','m','e',' ','h','e','r','e'}; |
| static const uint_16 USB_STR_n[17] = {0x0300 + sizeof(USB_STR_n), |
| 'B','A','D',' ','S','T','R','I','N','G',' ','I','n','d','e','x'}; |
| |
| #define USB_STRING_ARRAY_SIZE 8 |
| static const uint_8_ptr USB_STRING_DESC[USB_STRING_ARRAY_SIZE] = |
| { |
| (uint_8_ptr)USB_STR_0, |
| (uint_8_ptr)USB_STR_1, |
| (uint_8_ptr)USB_STR_2, |
| (uint_8_ptr)USB_STR_3, |
| (uint_8_ptr)USB_STR_4, |
| (uint_8_ptr)USB_STR_5, |
| (uint_8_ptr)USB_STR_6, |
| (uint_8_ptr)USB_STR_n |
| }; |
| |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : ch9GetDescription |
| * Returned Value : None |
| * Comments : |
| * Chapter 9 GetDescription command |
| * The Device Request can ask for Device/Config/string/interface/endpoint |
| * descriptors (via wValue). We then post an IN response to return the |
| * requested descriptor. |
| * And then wait for the OUT which terminates the control transfer. |
| * See section 9.4.3 (page 189) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void ch9GetDescription |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { /* Body */ |
| if (setup) { |
| /* Load the appropriate string depending on the descriptor requested.*/ |
| switch (setup_ptr->VALUE & 0xFF00) { |
| |
| case 0x0100: |
| _usb_device_send_data(handle, 0, DevDesc, |
| MIN(setup_ptr->LENGTH, DEVICE_DESCRIPTOR_SIZE)); |
| |
| break; |
| |
| case 0x0200: |
| *(ConfigDesc + 33) = frame_interval; |
| _usb_device_send_data(handle, 0, ConfigDesc, |
| MIN(setup_ptr->LENGTH, CONFIG_DESC_SIZE)); |
| |
| break; |
| |
| case 0x2200: |
| _usb_device_send_data(handle, 0, ReportDesc, |
| MIN(setup_ptr->LENGTH, REPORT_DESC_SIZE)); |
| |
| /*send some data for the mouse in the interrupt pipe queue */ |
| _usb_device_send_data(handle, INTERRUPT_EP, (uint_8_ptr)((pointer)&mouse_data), |
| sizeof(MOUSE_DATA_STRUCT)); |
| |
| break; |
| |
| case 0x0300: |
| if ((setup_ptr->VALUE & 0x00FF) > USB_STR_NUM) { |
| _usb_device_send_data(handle, 0, USB_STRING_DESC[USB_STR_NUM+1], |
| MIN(setup_ptr->LENGTH, USB_STRING_DESC[USB_STR_NUM+1][0])); |
| } else { |
| _usb_device_send_data(handle, 0, |
| USB_STRING_DESC[setup_ptr->VALUE & 0x00FF], |
| MIN(setup_ptr->LENGTH, USB_STRING_DESC[setup_ptr->VALUE & 0x00FF][0])); |
| } /* Endif */ |
| break; |
| |
| case 0x600: |
| _usb_device_send_data(handle, 0, (uint_8_ptr)DevQualifierDesc, |
| MIN(setup_ptr->LENGTH, DEVICE_QUALIFIER_DESCRIPTOR_SIZE)); |
| break; |
| |
| case 0x700: |
| *(other_speed_config + 33) = frame_interval; |
| |
| _usb_device_send_data(handle, 0, (uint_8_ptr)other_speed_config, |
| MIN(setup_ptr->LENGTH, OTHER_SPEED_CONFIG_DESC_SIZE)); |
| break; |
| |
| default: |
| USB_printf("usbMouse_%d, %s: Unexpected VALUE=0x%04x\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE); |
| _usb_device_stall_endpoint(handle, 0, 0); |
| return; |
| } /* Endswitch */ |
| /* status phase */ |
| _usb_device_recv_data(handle, 0, 0, 0); |
| } /* Endif */ |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : ch9SetDescription |
| * Returned Value : None |
| * Comments : |
| * Chapter 9 SetDescription command |
| * See section 9.4.8 (page 193) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void ch9SetDescription |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { /* Body */ |
| USB_printf("usbMouse_%d, %s: setup=%d\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, (int)setup); |
| _usb_device_stall_endpoint(handle, 0, 0); |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : ch9GetConfig |
| * Returned Value : None |
| * Comments : |
| * Chapter 9 GetConfig command |
| * See section 9.4.2 (page 189) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void ch9GetConfig |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { /* Body */ |
| uint_16 current_config; |
| /* Return the currently selected configuration */ |
| if (setup){ |
| _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, |
| ¤t_config); |
| data_to_send = (uint_8)current_config; |
| _usb_device_send_data(handle, 0, (pointer) &data_to_send, sizeof(data_to_send)); |
| /* status phase */ |
| _usb_device_recv_data(handle, 0, 0, 0); |
| } /* Endif */ |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : ch9SetConfig |
| * Returned Value : None |
| * Comments : |
| * Chapter 9 SetConfig command |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void ch9SetConfig |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { /* Body */ |
| uint_16 usb_state; |
| |
| if (setup) |
| { |
| if ((setup_ptr->VALUE & 0x00FF) > 1) |
| { |
| /* generate stall */ |
| USB_printf("usbMouse_%d, %s: Wrong VALUE=0x%04x\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE); |
| _usb_device_stall_endpoint(handle, 0, 0); |
| return; |
| } /* Endif */ |
| |
| /* 0 indicates return to unconfigured state */ |
| if ((setup_ptr->VALUE & 0x00FF) == 0) |
| { |
| _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state); |
| if ((usb_state == ARC_USB_STATE_CONFIG) || |
| (usb_state == ARC_USB_STATE_ADDRESS)) |
| { |
| /* clear the currently selected config value */ |
| _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, 0); |
| _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, |
| ARC_USB_STATE_ADDRESS); |
| /* status phase */ |
| _usb_device_send_data(handle, 0, 0, 0); |
| } |
| else |
| { |
| USB_printf("usbMouse_%d, %s: Wrong usb_state=%d\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, usb_state); |
| |
| _usb_device_stall_endpoint(handle, 0, 0); |
| } /* Endif */ |
| return; |
| } /* Endif */ |
| |
| /* |
| ** If the configuration value (setup_ptr->VALUE & 0x00FF) differs |
| ** from the current configuration value, then endpoints must be |
| ** reconfigured to match the new device configuration |
| */ |
| _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, &usb_state); |
| ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, |
| "usbMouse: Set configuration: old=%d, new=%d\n", |
| usb_state, setup_ptr->VALUE & 0x00FF); |
| |
| if (usb_state != (setup_ptr->VALUE & 0x00FF)) |
| { |
| /* Reconfigure endpoints here */ |
| switch (setup_ptr->VALUE & 0x00FF) |
| { |
| default: |
| break; |
| } /* Endswitch */ |
| _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, |
| setup_ptr->VALUE & 0x00FF); |
| } /* Endif */ |
| /* Init Interrupt endpoint */ |
| _usb_device_init_endpoint(handle,INTERRUPT_EP, INTERRUPT_MAX_PACKET_SIZE, |
| ARC_USB_SEND, ARC_USB_INTERRUPT_ENDPOINT, |
| ARC_USB_DEVICE_DONT_ZERO_TERMINATE); |
| |
| TEST_ENABLED = TRUE; |
| |
| _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, |
| ARC_USB_STATE_CONFIG); |
| /* status phase */ |
| _usb_device_send_data(handle, 0, 0, 0); |
| } /* Endif */ |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : ch9GetInterface |
| * Returned Value : None |
| * Comments : |
| * Chapter 9 GetInterface command |
| * See section 9.4.4 (page 190) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void ch9GetInterface |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { /* Body */ |
| uint_16 usb_state; |
| |
| _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state); |
| if (usb_state != ARC_USB_STATE_CONFIG) |
| { |
| USB_printf("usbMouse_%d, %s: Wrong usb_state=%d\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, usb_state); |
| _usb_device_stall_endpoint(handle, 0, 0); |
| return; |
| } /* Endif */ |
| |
| if (setup) |
| { |
| _usb_device_send_data(handle, 0, &USB_IF_ALT[setup_ptr->INDEX & 0x00FF], |
| MIN(setup_ptr->LENGTH, sizeof(uint_8))); |
| /* status phase */ |
| _usb_device_recv_data(handle, 0, 0, 0); |
| } /* Endif */ |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : ch9SetInterface |
| * Returned Value : None |
| * Comments : |
| * Chapter 9 SetInterface command |
| * See section 9.4.10 (page 195) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void ch9SetInterface |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { /* Body */ |
| if (setup) |
| { |
| if (setup_ptr->REQUESTTYPE != 0x01) |
| { |
| USB_printf("usbDisk_%d, %s: Wrong REQUESTTYPE=0x%02x\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, |
| setup_ptr->REQUESTTYPE); |
| |
| _usb_device_stall_endpoint(handle, 0, 0); |
| return; |
| } /* Endif */ |
| |
| /* |
| ** If the alternate value (setup_ptr->VALUE & 0x00FF) differs |
| ** from the current alternate value for the specified interface, |
| ** then endpoints must be reconfigured to match the new alternate |
| */ |
| if (USB_IF_ALT[setup_ptr->INDEX & 0x00FF] |
| != (setup_ptr->VALUE & 0x00FF)) |
| { |
| USB_IF_ALT[setup_ptr->INDEX & 0x00FF] = (setup_ptr->VALUE & 0x00FF); |
| /* Reconfigure endpoints here. */ |
| |
| } /* Endif */ |
| |
| /* status phase */ |
| _usb_device_send_data(handle, 0, 0, 0); |
| } /* Endif */ |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : ch9SynchFrame |
| * Returned Value : |
| * Comments : |
| * Chapter 9 SynchFrame command |
| * See section 9.4.11 (page 195) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void ch9SynchFrame |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { /* Body */ |
| |
| if (setup) |
| { |
| if (setup_ptr->REQUESTTYPE != 0x02) |
| { |
| USB_printf("usbMouse_%d, %s: Wrong REQUESTTYPE=0x%02x\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, |
| setup_ptr->REQUESTTYPE); |
| _usb_device_stall_endpoint(handle, 0, 0); |
| return; |
| } /* Endif */ |
| |
| if ((setup_ptr->INDEX & 0x00FF) >= |
| ConfigDesc[CONFIG_DESC_NUM_INTERFACES]) |
| { |
| USB_printf("usbMouse_%d, %s: Wrong INDEX=0x%04x\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->INDEX); |
| _usb_device_stall_endpoint(handle, 0, 0); |
| return; |
| } /* Endif */ |
| |
| _usb_device_get_status(handle, ARC_USB_STATUS_SOF_COUNT, &sof_count); |
| |
| sof_count = USB_16BIT_LE(sof_count); |
| _usb_device_send_data(handle, 0, (uint_8_ptr)&sof_count, |
| MIN(setup_ptr->LENGTH, sizeof(sof_count))); |
| /* status phase */ |
| _usb_device_recv_data(handle, 0, 0, 0); |
| } /* Endif */ |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : get_report |
| * Returned Value : |
| * Comments : |
| * Chapter 9 Class specific request |
| * See section 9.4.11 (page 195) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| |
| void get_report |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* [IN] Direction of the transfer. (1 for USB IN token)*/ |
| uint_8 direction, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| |
| ) |
| { |
| int i; |
| |
| for(i=0;i<10;i++) |
| { |
| hid_test_rep_data[i] = (uint_8) i; |
| } |
| |
| if (setup) |
| { |
| _usb_device_send_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4)); |
| } |
| |
| _usb_device_recv_data(handle, 0, 0, 0); |
| |
| |
| return; |
| } |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : set_report |
| * Returned Value : |
| * Comments : |
| * Chapter 9 Class specific request |
| * See section 9.4.11 (page 195) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| |
| void set_report |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* [IN] Direction of the transfer. (1 for USB IN token)*/ |
| uint_8 direction, |
| |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { |
| if (setup) /*on a SetUP packet*/ |
| { |
| _usb_device_recv_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4)); |
| |
| } |
| else if(direction == ARC_USB_RECV) /*on a OUT packet*/ |
| { |
| _usb_device_recv_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4)); |
| _usb_device_send_data(handle, 0, 0, 0); |
| } |
| |
| return; |
| } |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : set_idle |
| * Returned Value : |
| * Comments : |
| * Chapter 9 Class specific request |
| * See section 9.4.11 (page 195) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| |
| void set_idle |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* [IN] Direction of the transfer. (1 for USB IN token)*/ |
| uint_8 direction, |
| |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { |
| /* SET_IDLE is a No data phase transaction from HID class. All it needs |
| is a terminating IN token */ |
| if (setup) /*on a SetUP packet*/ |
| { |
| _usb_device_send_data(handle, 0, 0, 0); |
| } |
| return; |
| } |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : ch9Class |
| * Returned Value : |
| * Comments : |
| * Chapter 9 Class specific request |
| * See section 9.4.11 (page 195) of the USB 1.1 Specification. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void ch9Class |
| ( |
| /* USB handle */ |
| _usb_device_handle handle, |
| |
| /* Is it a Setup phase? */ |
| boolean setup, |
| |
| /* [IN] Direction of the transfer. (1 for USB IN token)*/ |
| uint_8 direction, |
| |
| /* The setup packet pointer */ |
| SETUP_STRUCT_PTR setup_ptr |
| ) |
| { /* Body */ |
| |
| switch (setup_ptr->REQUEST) |
| { |
| |
| case 0x01: |
| get_report(handle, setup, direction, setup_ptr); |
| break; |
| |
| case 0x09: |
| set_report(handle, setup, direction, setup_ptr); |
| break; |
| |
| case 0x0A: |
| set_idle(handle, setup, direction, setup_ptr); |
| break; |
| |
| default: |
| USB_printf("usbMouse_%d, %s: Wrong REQUEST=0x%02x\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->REQUEST); |
| |
| _usb_device_stall_endpoint(handle, 0, 0); |
| break; |
| |
| } /* EndSwitch */ |
| |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : service_ep0 |
| * Returned Value : None |
| * Comments : |
| * Called upon a completed endpoint 0 (USB 1.1 Chapter 9) transfer |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void service_ep0 |
| ( |
| /* [IN] Handle of the USB device */ |
| _usb_device_handle handle, |
| |
| /* [IN] request type as registered */ |
| uint_8 type, |
| |
| /* [IN] Is it a setup packet? */ |
| boolean setup, |
| |
| /* [IN] Direction of the transfer. Is it transmit? */ |
| uint_8 direction, |
| |
| /* [IN] Pointer to the data buffer */ |
| uint_8_ptr buffer, |
| |
| /* [IN] Length of the transfer */ |
| uint_32 length, |
| |
| /* [IN] Error, if any */ |
| uint_8 error |
| |
| |
| ) |
| { /* Body */ |
| boolean class_request = FALSE; |
| |
| if (setup) |
| { |
| _usb_device_read_setup_data(handle, 0, (uint_8_ptr)&local_setup_packet); |
| local_setup_packet.VALUE = USB_16BIT_LE(local_setup_packet.VALUE); |
| local_setup_packet.INDEX = USB_16BIT_LE(local_setup_packet.INDEX); |
| local_setup_packet.LENGTH = USB_16BIT_LE(local_setup_packet.LENGTH); |
| } |
| else if (class_request) { |
| class_request = FALSE; |
| /* Finish your class or vendor request here */ |
| |
| return; |
| } /* Endif */ |
| |
| switch (local_setup_packet.REQUESTTYPE & 0x60) { |
| |
| case 0x00: |
| switch (local_setup_packet.REQUEST) { |
| |
| case 0x0: |
| mvUsbCh9GetStatus(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0x1: |
| mvUsbCh9ClearFeature(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0x3: |
| mvUsbCh9SetFeature(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0x5: |
| mvUsbCh9SetAddress(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0x6: |
| ch9GetDescription(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0x7: |
| ch9SetDescription(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0x8: |
| ch9GetConfig(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0x9: |
| ch9SetConfig(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0xa: |
| ch9GetInterface(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0xb: |
| ch9SetInterface(handle, setup, &local_setup_packet); |
| break; |
| |
| case 0xc: |
| ch9SynchFrame(handle, setup, &local_setup_packet); |
| break; |
| |
| default: |
| USB_printf("usbMouse_%d, %s: Wrong REQUEST = 0x%02x\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, local_setup_packet.REQUEST); |
| _usb_device_stall_endpoint(handle, 0, 0); |
| break; |
| |
| } /* Endswitch */ |
| |
| break; |
| |
| case 0x20: |
| ch9Class(handle, setup, direction, &local_setup_packet); |
| |
| break; |
| |
| case 0x40: |
| /* vendor specific request */ |
| break; |
| |
| default: |
| USB_printf("usbMouse_%d, %s: Unexpected REQUESTTYPE = 0x%x\n", |
| _usb_device_get_dev_num(handle), __FUNCTION__, |
| local_setup_packet.REQUESTTYPE); |
| |
| _usb_device_stall_endpoint(handle, 0, 0); |
| break; |
| |
| } /* Endswitch */ |
| |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : service_ep1 |
| * Returned Value : None |
| * Comments : |
| * Called upon a completed endpoint 1 (USB 1.1 Chapter 9) transfer |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void service_ep1 |
| ( |
| /* [IN] Handle of the USB device */ |
| _usb_device_handle handle, |
| |
| /* [IN] request type as registered */ |
| uint_8 type, |
| |
| /* [IN] Is it a setup packet? */ |
| boolean setup, |
| |
| /* [IN] Direction of the transfer. Is it transmit? */ |
| uint_8 direction, |
| |
| /* [IN] Pointer to the data buffer */ |
| uint_8_ptr buffer, |
| |
| /* [IN] Length of the transfer */ |
| uint_32 length, |
| |
| /* [IN] Error, if any */ |
| uint_8 error |
| |
| |
| ) |
| { /* Body */ |
| |
| /******************************************************************** |
| The following code will move the mouse right and left on the screen. |
| Comment this out if this behaviour is not desired. |
| ********************************************************************/ |
| |
| static int x = 0; |
| static boolean right = FALSE; |
| static int wait = 0; |
| |
| mouseCntr++; |
| if(wait == 0) |
| { |
| if (right == FALSE) |
| { |
| mouse_data.b = 1; |
| x++; |
| right = (x > 200) ? TRUE : FALSE; |
| } |
| |
| if (right == TRUE) |
| { |
| mouse_data.b = -1; |
| x--; |
| right = (x < 0) ? FALSE : TRUE; |
| } |
| wait = mouseDelay; |
| } |
| else |
| { |
| wait--; |
| mouse_data.b = 0; |
| } |
| |
| _usb_device_send_data(handle, INTERRUPT_EP, (uint_8_ptr)((pointer)&mouse_data), |
| sizeof(MOUSE_DATA_STRUCT)); |
| |
| return; |
| } /* Endbody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : reset_ep0 |
| * Returned Value : None |
| * Comments : |
| * Called upon a bus reset event. Initialises the control endpoint. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void reset_ep0 |
| ( |
| /* [IN] Handle of the USB device */ |
| _usb_device_handle handle, |
| |
| /* [IN] request type as registered */ |
| uint_8 type, |
| |
| /* [IN] Unused */ |
| boolean setup, |
| |
| /* [IN] Unused */ |
| uint_8 direction, |
| |
| /* [IN] Unused */ |
| uint_8_ptr buffer, |
| |
| /* [IN] Unused */ |
| uint_32 length, |
| |
| /* [IN] Error, if any */ |
| uint_8 error |
| |
| |
| ) |
| { /* Body */ |
| |
| /*on a reset always cancel all transfers all EP 0 */ |
| _usb_device_cancel_transfer(handle, 0, ARC_USB_RECV); |
| _usb_device_cancel_transfer(handle, 0, ARC_USB_SEND); |
|
|
| _usb_device_start(handle);
|
| |
| /* Initialize the endpoint 0 in both directions */ |
| _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 0, |
| ARC_USB_CONTROL_ENDPOINT, 0); |
| _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 1, |
| ARC_USB_CONTROL_ENDPOINT, 0); |
| |
| if (TEST_ENABLED) |
| { |
| _usb_device_cancel_transfer(handle, INTERRUPT_EP, ARC_USB_SEND); |
| } /* Endif */ |
| |
| TEST_ENABLED = FALSE; |
| mouseCntr = 0; |
| |
| return; |
| } /* EndBody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : service_suspend |
| * Returned Value : None |
| * Comments : |
| * Called when host suspend the USB port. Do remote wake up if desired. |
| * |
| *END*--------------------------------------------------------------------*/ |
| static void service_suspend |
| ( |
| /* [IN] Handle of the USB device */ |
| _usb_device_handle handle, |
| |
| /* [IN] request type as registered */ |
| uint_8 type, |
| |
| /* [IN] Unused */ |
| boolean setup, |
| |
| /* [IN] Unused */ |
| uint_8 direction, |
| |
| /* [IN] Unused */ |
| uint_8_ptr buffer, |
| |
| /* [IN] Unused */ |
| uint_32 length, |
| |
| /* [IN] Error, if any */ |
| uint_8 error |
| ) |
| { /* Body */ |
| uint_16 usb_status; |
| int lockKey; |
| |
| _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status); |
| if (usb_status & ARC_USB_REMOTE_WAKEUP) |
| { |
| lockKey = USB_lock(); |
| |
| USB_printf("Mouse Suspended: type=%d, usbStatus=0x%x\n", type, usb_status); |
| USB_SUSPENDED = TRUE; |
| |
| USB_unlock(lockKey); |
| } |
| |
| return; |
| } /* EndBody */ |
| |
| /*FUNCTION*---------------------------------------------------------------- |
| * |
| * Function Name : usbMouseLoad |
| * Returned Value : None |
| * Comments : |
| * First function called. Initialises the USB and registers Chapter 9 |
| * callback functions. |
| * |
| *END*--------------------------------------------------------------------*/ |
| _usb_device_handle usbMouseLoad(int devNo) |
| { /* Body */ |
| _usb_device_handle handle; |
| uint_8 error; |
| uint_32 send_data_buffer_size=0; |
| uint_8_ptr temp; |
| int lockKey, i, j; |
| static boolean isFirst = TRUE; |
| |
| if(isFirst) |
| { |
| /* Swap all USB_STRING_DESC */ |
| for(i=0; i<(sizeof(USB_STRING_DESC)/sizeof(USB_STRING_DESC[0])); i++) |
| { |
| uint_16* usbStr = (uint_16*)(USB_STRING_DESC[i]); |
| uint_16 size = (usbStr[0]-0x300)/sizeof(uint_16); |
| |
| for(j=0; j<size; j++) |
| { |
| usbStr[j] = USB_16BIT_LE(usbStr[j]); |
| } |
| } |
| isFirst = FALSE; |
| } |
| |
| lockKey = USB_lock(); |
| |
| /* Initialize the USB interface */ |
| error = _usb_device_init(devNo, &handle); |
| if (error != USB_OK) |
| { |
| USB_printf("\nUSB Initialization failed. Error: %x\n", error); |
| return NULL; |
| } /* Endif */ |
| |
| /* Self Power, Remote wakeup disable */ |
| _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, (1 << DEVICE_SELF_POWERED)); |
| |
| error = _usb_device_register_service(handle, ARC_USB_SERVICE_EP0, service_ep0); |
| if (error != USB_OK) |
| { |
| USB_printf("\nUSB EP0 Service Registration failed. Error: %x\n", error); |
| return NULL; |
| } /* Endif */ |
| |
| error = _usb_device_register_service(handle, ARC_USB_SERVICE_BUS_RESET, reset_ep0); |
| if (error != USB_OK) |
| { |
| USB_printf("\nUSB BUS_RESET Service Registration failed. Error: %x\n", error); |
| return NULL; |
| } /* Endif */ |
| |
| error = _usb_device_register_service(handle, INTERRUPT_EP, service_ep1); |
| if (error != USB_OK) |
| { |
| USB_printf("\nUSB EP1 Service Registration failed. Error: %x\n", error); |
| return NULL; |
| } /* Endif */ |
| |
| error = _usb_device_register_service(handle, ARC_USB_SERVICE_SUSPEND, service_suspend); |
| if (error != USB_OK) |
| { |
| USB_printf("\nUSB SUSPEND Service Registration failed. Error: %x\n", error); |
| return NULL; |
| } /* Endif */ |
| |
| error = _usb_device_register_service(handle, ARC_USB_SERVICE_SLEEP, service_suspend); |
| if (error != USB_OK) |
| { |
| USB_printf("\nUSB SUSPEND Service Registration failed. Error: %x\n", error); |
| return NULL; |
| } /* Endif */ |
| |
| /*********************************************************************** |
| Allocate memory to receive data at endpoint 0. Ensure that buffers are |
| cache aligned. |
| ***********************************************************************/ |
| hid_test_rep_data_unaligned = (uint_8_ptr) USB_memalloc((EP1_RECV_BUFFER_SIZE + PSP_CACHE_LINE_SIZE)); |
| if(hid_test_rep_data_unaligned == NULL) |
| { |
| USB_printf("mouseLoad: Buffer allocation of %d bytes is failed\n", |
| (unsigned)EP1_RECV_BUFFER_SIZE + PSP_CACHE_LINE_SIZE); |
| return NULL; |
| } |
| |
| hid_test_rep_data = (uint_8_ptr) USB_CACHE_ALIGN((uint_32) hid_test_rep_data_unaligned); |
| |
| /************************************************************************** |
| Best way to handle the Data cache is to allocate a large buffer that is |
| cache aligned and keep all data inside it. Flush the line of the cache |
| that you have changed. In this program, we have static data such as |
| descriptors which never changes. Such data can be kept in this buffer |
| and flushed only once. Note that you can reduce the size of this buffer |
| by aligning the addresses in a different way. |
| ***************************************************************************/ |
| send_data_buffer_size = (DEVICE_DESCRIPTOR_SIZE + PSP_CACHE_LINE_SIZE) + |
| (CONFIG_DESC_SIZE + PSP_CACHE_LINE_SIZE) + |
| (REPORT_DESC_SIZE + PSP_CACHE_LINE_SIZE) + |
| (DEVICE_QUALIFIER_DESCRIPTOR_SIZE + PSP_CACHE_LINE_SIZE) + |
| (OTHER_SPEED_CONFIG_DESC_SIZE + PSP_CACHE_LINE_SIZE); |
| |
| Send_Buffer_Unaligned = (uint_8_ptr) USB_memalloc(send_data_buffer_size); |
| if (Send_Buffer_Unaligned == NULL) |
| { |
| USB_printf("\nMouse: %d bytes Buffer allocation failed\n", send_data_buffer_size); |
| return NULL; |
| } |
| |
| Send_Buffer_aligned = (uint_8_ptr) USB_CACHE_ALIGN((uint_32) Send_Buffer_Unaligned); |
| /* keep a temporary copy of the aligned address */ |
| temp = Send_Buffer_aligned; |
| |
| |
| /************************************************************************** |
| Assign pointers to different descriptors from it and copy descriptors inside. |
| ***************************************************************************/ |
| DevDesc = (uint_8_ptr) Send_Buffer_aligned; |
| USB_memcopy(DevDescData, DevDesc, DEVICE_DESCRIPTOR_SIZE); |
| Send_Buffer_aligned += ((DEVICE_DESCRIPTOR_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; |
| |
| ConfigDesc = (uint_8_ptr) Send_Buffer_aligned; |
| USB_memcopy(ConfigDescData, ConfigDesc, CONFIG_DESC_SIZE); |
| |
| Send_Buffer_aligned += ((CONFIG_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; |
| |
| ReportDesc = (uint_8_ptr) Send_Buffer_aligned; |
| USB_memcopy(ReportDescData, ReportDesc, REPORT_DESC_SIZE); |
| Send_Buffer_aligned += ((REPORT_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; |
| |
| |
| DevQualifierDesc = (uint_8_ptr) Send_Buffer_aligned; |
| USB_memcopy(DevQualifierDescData, DevQualifierDesc, DEVICE_QUALIFIER_DESCRIPTOR_SIZE); |
| Send_Buffer_aligned += ((DEVICE_QUALIFIER_DESCRIPTOR_SIZE/PSP_CACHE_LINE_SIZE) + \ |
| 1)* PSP_CACHE_LINE_SIZE; |
| |
| other_speed_config = (uint_8_ptr) Send_Buffer_aligned; |
| USB_memcopy(other_speed_config_data, other_speed_config, OTHER_SPEED_CONFIG_DESC_SIZE); |
| Send_Buffer_aligned += ((OTHER_SPEED_CONFIG_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; |
| |
| /************************************************************************** |
| Flush the cache to ensure main memory is updated. |
| ***************************************************************************/ |
| USB_dcache_flush(temp,send_data_buffer_size); |
| |
| /* Initialize the endpoint 0 in both directions */ |
| _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 0, |
| ARC_USB_CONTROL_ENDPOINT, 0); |
| _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 1, |
| ARC_USB_CONTROL_ENDPOINT, 0); |
| |
| USB_unlock(lockKey); |
| |
| USB_printf("USB Mouse example is READY\n"); |
| |
| return handle; |
| } /* Endbody */ |
| |
| void usbMouseUnload(_usb_device_handle handle) |
| { |
| int lockKey; |
| |
| if(handle == NULL) |
| return; |
| |
| /*lock interrupts */ |
| lockKey = USB_lock(); |
| |
| /* ensure all transfers are cancelled */ |
| _usb_device_cancel_transfer(handle, INTERRUPT_EP, ARC_USB_SEND); |
| |
| /* Stop Endpoints */ |
| _usb_device_deinit_endpoint(handle, INTERRUPT_EP, ARC_USB_SEND); |
| |
| _usb_device_deinit_endpoint(handle, 0, ARC_USB_RECV); |
| _usb_device_deinit_endpoint(handle, 0, ARC_USB_SEND); |
|
|
| _usb_device_stop(handle);
|
| |
| /* Deregister all services */ |
| _usb_device_unregister_service(handle, ARC_USB_SERVICE_EP0); |
| _usb_device_unregister_service(handle, ARC_USB_SERVICE_BUS_RESET); |
| _usb_device_unregister_service(handle, ARC_USB_SERVICE_SUSPEND); |
| _usb_device_unregister_service(handle, ARC_USB_SERVICE_SLEEP); |
| _usb_device_unregister_service(handle, INTERRUPT_EP); |
| |
| _usb_device_shutdown(handle); |
| |
| /* Free memory allocated for Disk device */ |
| if(Send_Buffer_Unaligned != NULL) |
| { |
| USB_memfree(Send_Buffer_Unaligned); |
| Send_Buffer_Unaligned = NULL; |
| } |
| |
| if(hid_test_rep_data_unaligned != NULL) |
| { |
| USB_memfree(hid_test_rep_data_unaligned); |
| hid_test_rep_data_unaligned = NULL; |
| } |
| |
| /* Clear gloabal variables */ |
| TEST_ENABLED = FALSE; |
| USB_SUSPENDED = FALSE; |
| |
| USB_unlock(lockKey); |
| } |
| |
| void usbMousePeriodicResume(_usb_device_handle handle) |
| { |
| if (USB_SUSPENDED) |
| { |
| /* |
| * Send RESUME signal whenever host suspends the USB port. In real case, we should |
| * send RESUME signal only when a mouse button being clicked. |
| */ |
| USB_printf("Mouse Resumed\n"); |
| |
| _usb_device_assert_resume(handle); |
| USB_SUSPENDED = FALSE; |
| } /* Endbody */ |
| } |
| /* EOF */ |