2018.07.26

Dependencies:   FATFileSystem3 mbed-rtos

Fork of USBHost by mbed official

Committer:
sayzyas
Date:
Tue Jun 02 05:57:44 2015 +0000
Revision:
32:e6717a485577
Child:
33:86c22c0c8aae
20150602

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sayzyas 32:e6717a485577 1 /* mbed USBHost Gamepad driver sample
sayzyas 32:e6717a485577 2 * Copyright (c) 2014 Yuuichi Akagawa
sayzyas 32:e6717a485577 3 *
sayzyas 32:e6717a485577 4 * modified from mbed USBHostMouse
sayzyas 32:e6717a485577 5 *
sayzyas 32:e6717a485577 6 * mbed USBHost Library
sayzyas 32:e6717a485577 7 * Copyright (c) 2006-2013 ARM Limited
sayzyas 32:e6717a485577 8 *
sayzyas 32:e6717a485577 9 * Licensed under the Apache License, Version 2.0 (the "License");
sayzyas 32:e6717a485577 10 * you may not use this file except in compliance with the License.
sayzyas 32:e6717a485577 11 * You may obtain a copy of the License at
sayzyas 32:e6717a485577 12 *
sayzyas 32:e6717a485577 13 * http://www.apache.org/licenses/LICENSE-2.0
sayzyas 32:e6717a485577 14 *
sayzyas 32:e6717a485577 15 * Unless required by applicable law or agreed to in writing, software
sayzyas 32:e6717a485577 16 * distributed under the License is distributed on an "AS IS" BASIS,
sayzyas 32:e6717a485577 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sayzyas 32:e6717a485577 18 * See the License for the specific language governing permissions and
sayzyas 32:e6717a485577 19 * limitations under the License.
sayzyas 32:e6717a485577 20 * Refer to following URL:
sayzyas 32:e6717a485577 21 * https://developer.mbed.org/users/YuuichiAkagawa/code/USBHostGamepad/file/7345e2afa41e/USBHostGamepad.cpp
sayzyas 32:e6717a485577 22 */
sayzyas 32:e6717a485577 23 #include "USBHostGamepad.h"
sayzyas 32:e6717a485577 24 //#if USBHOST_GAMEPAD
sayzyas 32:e6717a485577 25
sayzyas 32:e6717a485577 26 USBHostGamepad::USBHostGamepad() {
sayzyas 32:e6717a485577 27 host = USBHost::getHostInst();
sayzyas 32:e6717a485577 28 init();
sayzyas 32:e6717a485577 29 }
sayzyas 32:e6717a485577 30
sayzyas 32:e6717a485577 31 void USBHostGamepad::init() {
sayzyas 32:e6717a485577 32 dev = NULL;
sayzyas 32:e6717a485577 33 int_in = NULL;
sayzyas 32:e6717a485577 34 onUpdate = NULL;
sayzyas 32:e6717a485577 35 report_id = 0;
sayzyas 32:e6717a485577 36 dev_connected = false;
sayzyas 32:e6717a485577 37 gamepad_device_found = false;
sayzyas 32:e6717a485577 38 gamepad_intf = -1;
sayzyas 32:e6717a485577 39
sayzyas 32:e6717a485577 40 btnX = 0;
sayzyas 32:e6717a485577 41 btnY = 0;
sayzyas 32:e6717a485577 42 btnABCD = 0;
sayzyas 32:e6717a485577 43 btnSpecial = 0;
sayzyas 32:e6717a485577 44 }
sayzyas 32:e6717a485577 45
sayzyas 32:e6717a485577 46 bool USBHostGamepad::connected() {
sayzyas 32:e6717a485577 47 return dev_connected;
sayzyas 32:e6717a485577 48 }
sayzyas 32:e6717a485577 49
sayzyas 32:e6717a485577 50 bool USBHostGamepad::connect() {
sayzyas 32:e6717a485577 51 int len_listen;
sayzyas 32:e6717a485577 52
sayzyas 32:e6717a485577 53 if (dev_connected) {
sayzyas 32:e6717a485577 54 return true;
sayzyas 32:e6717a485577 55 }
sayzyas 32:e6717a485577 56
sayzyas 32:e6717a485577 57 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
sayzyas 32:e6717a485577 58 if ((dev = host->getDevice(i)) != NULL) {
sayzyas 32:e6717a485577 59
sayzyas 32:e6717a485577 60 if(host->enumerate(dev, this))
sayzyas 32:e6717a485577 61 break;
sayzyas 32:e6717a485577 62
sayzyas 32:e6717a485577 63 if (gamepad_device_found) {
sayzyas 32:e6717a485577 64
sayzyas 32:e6717a485577 65 int_in = dev->getEndpoint(gamepad_intf, INTERRUPT_ENDPOINT, IN);
sayzyas 32:e6717a485577 66 if (!int_in)
sayzyas 32:e6717a485577 67 break;
sayzyas 32:e6717a485577 68
sayzyas 32:e6717a485577 69 USB_INFO("New Gamepad/Joystick device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, gamepad_intf);
sayzyas 32:e6717a485577 70 #if DEBUG > 3
sayzyas 32:e6717a485577 71 //Parse HID Report Descriptor
sayzyas 32:e6717a485577 72 parseHidDescr();
sayzyas 32:e6717a485577 73 #endif
sayzyas 32:e6717a485577 74 dev->setName("Gamepad", gamepad_intf);
sayzyas 32:e6717a485577 75 host->registerDriver(dev, gamepad_intf, this, &USBHostGamepad::init);
sayzyas 32:e6717a485577 76
sayzyas 32:e6717a485577 77 int_in->attach(this, &USBHostGamepad::rxHandler);
sayzyas 32:e6717a485577 78 len_listen = int_in->getSize();
sayzyas 32:e6717a485577 79 if (len_listen > sizeof(report)) {
sayzyas 32:e6717a485577 80 len_listen = sizeof(report);
sayzyas 32:e6717a485577 81 }
sayzyas 32:e6717a485577 82 host->interruptRead(dev, int_in, report, len_listen, false);
sayzyas 32:e6717a485577 83
sayzyas 32:e6717a485577 84 dev_connected = true;
sayzyas 32:e6717a485577 85 return true;
sayzyas 32:e6717a485577 86 }
sayzyas 32:e6717a485577 87 }
sayzyas 32:e6717a485577 88 }
sayzyas 32:e6717a485577 89 init();
sayzyas 32:e6717a485577 90 return false;
sayzyas 32:e6717a485577 91 }
sayzyas 32:e6717a485577 92
sayzyas 32:e6717a485577 93 void USBHostGamepad::rxHandler() {
sayzyas 32:e6717a485577 94 int len_listen = int_in->getSize();
sayzyas 32:e6717a485577 95 #if DEBUG > 3
sayzyas 32:e6717a485577 96 USB_DBG("USBHostGamepad::rxHandler() len_listen=%d\r\n", len_listen);
sayzyas 32:e6717a485577 97 for (int i = 0; i < len_listen; i++)
sayzyas 32:e6717a485577 98 printf("%02X ", report[i]);
sayzyas 32:e6717a485577 99 printf("\r\n\r\n");
sayzyas 32:e6717a485577 100 #endif
sayzyas 32:e6717a485577 101 if (onUpdate) {
sayzyas 32:e6717a485577 102 (*onUpdate)(report[0], report[1], report[5], report[6]);
sayzyas 32:e6717a485577 103 }
sayzyas 32:e6717a485577 104
sayzyas 32:e6717a485577 105 // update gamepad state
sayzyas 32:e6717a485577 106 btnX = report[0];
sayzyas 32:e6717a485577 107 btnY = report[1];
sayzyas 32:e6717a485577 108 btnABCD = report[5];
sayzyas 32:e6717a485577 109 btnSpecial = report[6];
sayzyas 32:e6717a485577 110
sayzyas 32:e6717a485577 111 if (len_listen > sizeof(report)) {
sayzyas 32:e6717a485577 112 len_listen = sizeof(report);
sayzyas 32:e6717a485577 113 }
sayzyas 32:e6717a485577 114
sayzyas 32:e6717a485577 115 if (dev)
sayzyas 32:e6717a485577 116 host->interruptRead(dev, int_in, report, len_listen, false);
sayzyas 32:e6717a485577 117 }
sayzyas 32:e6717a485577 118
sayzyas 32:e6717a485577 119 /*virtual*/ void USBHostGamepad::setVidPid(uint16_t vid, uint16_t pid)
sayzyas 32:e6717a485577 120 {
sayzyas 32:e6717a485577 121 // we don't check VID/PID for gamepad driver
sayzyas 32:e6717a485577 122 }
sayzyas 32:e6717a485577 123
sayzyas 32:e6717a485577 124 /*virtual*/ bool USBHostGamepad::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
sayzyas 32:e6717a485577 125 {
sayzyas 32:e6717a485577 126 if ((gamepad_intf == -1) &&
sayzyas 32:e6717a485577 127 (intf_class == HID_CLASS) &&
sayzyas 32:e6717a485577 128 (intf_subclass == 0x00) &&
sayzyas 32:e6717a485577 129 (intf_protocol == 0x00)) {
sayzyas 32:e6717a485577 130 gamepad_intf = intf_nb;
sayzyas 32:e6717a485577 131 return true;
sayzyas 32:e6717a485577 132 }
sayzyas 32:e6717a485577 133 return false;
sayzyas 32:e6717a485577 134 }
sayzyas 32:e6717a485577 135
sayzyas 32:e6717a485577 136 /*virtual*/ bool USBHostGamepad::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
sayzyas 32:e6717a485577 137 {
sayzyas 32:e6717a485577 138 if (intf_nb == gamepad_intf) {
sayzyas 32:e6717a485577 139 if (type == INTERRUPT_ENDPOINT && dir == IN) {
sayzyas 32:e6717a485577 140 gamepad_device_found = true;
sayzyas 32:e6717a485577 141 return true;
sayzyas 32:e6717a485577 142 }
sayzyas 32:e6717a485577 143 }
sayzyas 32:e6717a485577 144 return false;
sayzyas 32:e6717a485577 145 }
sayzyas 32:e6717a485577 146
sayzyas 32:e6717a485577 147 USB_TYPE USBHostGamepad::getReportDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_rep_descr)
sayzyas 32:e6717a485577 148 {
sayzyas 32:e6717a485577 149 USB_TYPE t = host->controlRead( dev,
sayzyas 32:e6717a485577 150 USB_DEVICE_TO_HOST | USB_RECIPIENT_INTERFACE | USB_REQUEST_TYPE_STANDARD,
sayzyas 32:e6717a485577 151 HID_GET_DESCRIPTOR,
sayzyas 32:e6717a485577 152 0x2200,
sayzyas 32:e6717a485577 153 0, buf, max_len_buf);
sayzyas 32:e6717a485577 154 if (len_rep_descr)
sayzyas 32:e6717a485577 155 *len_rep_descr = max_len_buf;
sayzyas 32:e6717a485577 156
sayzyas 32:e6717a485577 157 return t;
sayzyas 32:e6717a485577 158 }
sayzyas 32:e6717a485577 159
sayzyas 32:e6717a485577 160 /*
sayzyas 32:e6717a485577 161 * HID Report Descriptor parser
sayzyas 32:e6717a485577 162 */
sayzyas 32:e6717a485577 163 bool USBHostGamepad::parseHidDescr()
sayzyas 32:e6717a485577 164 {
sayzyas 32:e6717a485577 165 bool ret = true;
sayzyas 32:e6717a485577 166 uint8_t *buf;
sayzyas 32:e6717a485577 167 uint16_t desclen = host->getLengthReportDescr();
sayzyas 32:e6717a485577 168
sayzyas 32:e6717a485577 169 //allocate report descriptor's buffer
sayzyas 32:e6717a485577 170 buf = (uint8_t *)malloc(desclen);
sayzyas 32:e6717a485577 171 if(buf == NULL){
sayzyas 32:e6717a485577 172 return false;
sayzyas 32:e6717a485577 173 }
sayzyas 32:e6717a485577 174 getReportDescriptor(dev, buf, desclen);
sayzyas 32:e6717a485577 175 #if (DEBUG > 3)
sayzyas 32:e6717a485577 176 USB_DBG("HID REPORT DESCRIPTOR:\r\n");
sayzyas 32:e6717a485577 177 for (int i = 0; i < desclen; i++)
sayzyas 32:e6717a485577 178 printf("%02X ", buf[i]);
sayzyas 32:e6717a485577 179 printf("\r\n\r\n");
sayzyas 32:e6717a485577 180 #endif
sayzyas 32:e6717a485577 181 if( buf[0] == 0x05 //Usage page
sayzyas 32:e6717a485577 182 && buf[1] == 0x01 //Generic Desktop
sayzyas 32:e6717a485577 183 && buf[2] == 0x09 //Usage
sayzyas 32:e6717a485577 184 ){
sayzyas 32:e6717a485577 185 if( buf[3] == 0x04 ){
sayzyas 32:e6717a485577 186 USB_DBG("GAMEPAD");
sayzyas 32:e6717a485577 187 }else if( buf[3] == 0x05){
sayzyas 32:e6717a485577 188 USB_DBG("JOYSTICK");
sayzyas 32:e6717a485577 189 }else{
sayzyas 32:e6717a485577 190 ret = false;
sayzyas 32:e6717a485577 191 }
sayzyas 32:e6717a485577 192 }
sayzyas 32:e6717a485577 193 free(buf);
sayzyas 32:e6717a485577 194 return ret;
sayzyas 32:e6717a485577 195 }
sayzyas 32:e6717a485577 196 //#endif