/******************************************************************************* 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