Add USB HID Gamepad hosting support to mbed board (depends on USBHost library)

Dependents:   mbed_gamepad_example

Committer:
abougouffa
Date:
Wed Dec 20 11:19:12 2017 +0000
Revision:
1:b12dbbe77a8a
Parent:
0:5311825d0590
Add the USBHost library as dependency

Who changed what in which revision?

UserRevisionLine numberNew contents of line
abougouffa 0:5311825d0590 1 /* mbed USBHost Library
abougouffa 0:5311825d0590 2 * Copyright (c) 2006-2013 ARM Limited
abougouffa 0:5311825d0590 3 *
abougouffa 0:5311825d0590 4 * Licensed under the Apache License, Version 2.0 (the "License");
abougouffa 0:5311825d0590 5 * you may not use this file except in compliance with the License.
abougouffa 0:5311825d0590 6 * You may obtain a copy of the License at
abougouffa 0:5311825d0590 7 *
abougouffa 0:5311825d0590 8 * http://www.apache.org/licenses/LICENSE-2.0
abougouffa 0:5311825d0590 9 *
abougouffa 0:5311825d0590 10 * Unless required by applicable law or agreed to in writing, software
abougouffa 0:5311825d0590 11 * distributed under the License is distributed on an "AS IS" BASIS,
abougouffa 0:5311825d0590 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
abougouffa 0:5311825d0590 13 * See the License for the specific language governing permissions and
abougouffa 0:5311825d0590 14 * limitations under the License.
abougouffa 0:5311825d0590 15 */
abougouffa 0:5311825d0590 16
abougouffa 0:5311825d0590 17 #include "USBHostGamepad.h"
abougouffa 0:5311825d0590 18
abougouffa 0:5311825d0590 19 #if USBHOST_GAMEPAD
abougouffa 0:5311825d0590 20
abougouffa 0:5311825d0590 21 USBHostGamepad::USBHostGamepad()
abougouffa 0:5311825d0590 22 {
abougouffa 0:5311825d0590 23 host = USBHost::getHostInst();
abougouffa 0:5311825d0590 24 init();
abougouffa 0:5311825d0590 25 }
abougouffa 0:5311825d0590 26
abougouffa 0:5311825d0590 27 void USBHostGamepad::init()
abougouffa 0:5311825d0590 28 {
abougouffa 0:5311825d0590 29 dev = NULL;
abougouffa 0:5311825d0590 30 int_in = NULL;
abougouffa 0:5311825d0590 31 onUpdate = NULL;
abougouffa 0:5311825d0590 32 report_id = 0;
abougouffa 0:5311825d0590 33 dev_connected = false;
abougouffa 0:5311825d0590 34 gamepad_device_found = false;
abougouffa 0:5311825d0590 35 gamepad_intf = -1;
abougouffa 0:5311825d0590 36 }
abougouffa 0:5311825d0590 37
abougouffa 0:5311825d0590 38 bool USBHostGamepad::connected() {
abougouffa 0:5311825d0590 39 return dev_connected;
abougouffa 0:5311825d0590 40 }
abougouffa 0:5311825d0590 41
abougouffa 0:5311825d0590 42 bool USBHostGamepad::connect()
abougouffa 0:5311825d0590 43 {
abougouffa 0:5311825d0590 44 int len_listen;
abougouffa 0:5311825d0590 45
abougouffa 0:5311825d0590 46 if (dev_connected) {
abougouffa 0:5311825d0590 47 return true;
abougouffa 0:5311825d0590 48 }
abougouffa 0:5311825d0590 49
abougouffa 0:5311825d0590 50 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
abougouffa 0:5311825d0590 51
abougouffa 0:5311825d0590 52 if (dev = host->getDevice(i)) {
abougouffa 0:5311825d0590 53 if(host->enumerate(dev, this)) {
abougouffa 0:5311825d0590 54 break;
abougouffa 0:5311825d0590 55 }
abougouffa 0:5311825d0590 56 if (gamepad_device_found) {
abougouffa 0:5311825d0590 57 {
abougouffa 0:5311825d0590 58 /* As this is done in a specific thread
abougouffa 0:5311825d0590 59 * this lock is taken to avoid to process the device
abougouffa 0:5311825d0590 60 * disconnect in usb process during the device registering */
abougouffa 0:5311825d0590 61 USBHost::Lock Lock(host);
abougouffa 0:5311825d0590 62
abougouffa 0:5311825d0590 63 int_in = dev->getEndpoint(gamepad_intf, INTERRUPT_ENDPOINT, IN);
abougouffa 0:5311825d0590 64 if (!int_in) {
abougouffa 0:5311825d0590 65 break;
abougouffa 0:5311825d0590 66 }
abougouffa 0:5311825d0590 67
abougouffa 0:5311825d0590 68 USB_INFO("New Gamepad device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, gamepad_intf);
abougouffa 0:5311825d0590 69 dev->setName("Gamepad", gamepad_intf);
abougouffa 0:5311825d0590 70 host->registerDriver(dev, gamepad_intf, this, &USBHostGamepad::init);
abougouffa 0:5311825d0590 71
abougouffa 0:5311825d0590 72 int_in->attach(this, &USBHostGamepad::rxHandler);
abougouffa 0:5311825d0590 73 len_listen = int_in->getSize();
abougouffa 0:5311825d0590 74 if (len_listen > sizeof(report)) {
abougouffa 0:5311825d0590 75 len_listen = sizeof(report);
abougouffa 0:5311825d0590 76 }
abougouffa 0:5311825d0590 77 }
abougouffa 0:5311825d0590 78 int ret=host->interruptRead(dev, int_in, report, len_listen, false);
abougouffa 0:5311825d0590 79 MBED_ASSERT((ret==USB_TYPE_OK) || (ret ==USB_TYPE_PROCESSING) || (ret == USB_TYPE_FREE));
abougouffa 0:5311825d0590 80 if ((ret==USB_TYPE_OK) || (ret ==USB_TYPE_PROCESSING)) {
abougouffa 0:5311825d0590 81 dev_connected = true;
abougouffa 0:5311825d0590 82 }
abougouffa 0:5311825d0590 83 if (ret == USB_TYPE_FREE) {
abougouffa 0:5311825d0590 84 dev_connected = false;
abougouffa 0:5311825d0590 85 }
abougouffa 0:5311825d0590 86 return true;
abougouffa 0:5311825d0590 87 }
abougouffa 0:5311825d0590 88 }
abougouffa 0:5311825d0590 89 }
abougouffa 0:5311825d0590 90 init();
abougouffa 0:5311825d0590 91 return false;
abougouffa 0:5311825d0590 92 }
abougouffa 0:5311825d0590 93
abougouffa 0:5311825d0590 94 void USBHostGamepad::rxHandler()
abougouffa 0:5311825d0590 95 {
abougouffa 0:5311825d0590 96 int len_listen = int_in->getLengthTransferred();
abougouffa 0:5311825d0590 97
abougouffa 0:5311825d0590 98 if (len_listen !=0) {
abougouffa 0:5311825d0590 99 uint16_t buttons = 0x0;
abougouffa 0:5311825d0590 100 if (onUpdate) {
abougouffa 0:5311825d0590 101 buttons |= ((report[5] & 0xF0) >> 4) | (report[6] << 4);
abougouffa 0:5311825d0590 102 (*onUpdate)(report[0], report[1], report[3], report[4], buttons);
abougouffa 0:5311825d0590 103 }
abougouffa 0:5311825d0590 104 }
abougouffa 0:5311825d0590 105
abougouffa 0:5311825d0590 106 /* set again the maximum value */
abougouffa 0:5311825d0590 107 len_listen = int_in->getSize();
abougouffa 0:5311825d0590 108
abougouffa 0:5311825d0590 109 if (len_listen > sizeof(report)) {
abougouffa 0:5311825d0590 110 len_listen = sizeof(report);
abougouffa 0:5311825d0590 111 }
abougouffa 0:5311825d0590 112
abougouffa 0:5311825d0590 113 if (dev) {
abougouffa 0:5311825d0590 114 host->interruptRead(dev, int_in, report, len_listen, false);
abougouffa 0:5311825d0590 115 }
abougouffa 0:5311825d0590 116 }
abougouffa 0:5311825d0590 117
abougouffa 0:5311825d0590 118 /*virtual*/ void USBHostGamepad::setVidPid(uint16_t vid, uint16_t pid)
abougouffa 0:5311825d0590 119 {
abougouffa 0:5311825d0590 120 // we don't check VID/PID for Gamepad driver
abougouffa 0:5311825d0590 121 USB_INFO("VID: %X, PID: %X\n\r", vid, pid);
abougouffa 0:5311825d0590 122 }
abougouffa 0:5311825d0590 123
abougouffa 0:5311825d0590 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
abougouffa 0:5311825d0590 125 {
abougouffa 0:5311825d0590 126 if ((gamepad_intf == -1) &&
abougouffa 0:5311825d0590 127 (intf_class == HID_CLASS) &&
abougouffa 0:5311825d0590 128 (intf_subclass == 0x00) &&
abougouffa 0:5311825d0590 129 (intf_protocol == 0x00)) {
abougouffa 0:5311825d0590 130 gamepad_intf = intf_nb;
abougouffa 0:5311825d0590 131 return true;
abougouffa 0:5311825d0590 132 }
abougouffa 0:5311825d0590 133 return false;
abougouffa 0:5311825d0590 134 }
abougouffa 0:5311825d0590 135
abougouffa 0:5311825d0590 136 /*virtual*/ bool USBHostGamepad::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
abougouffa 0:5311825d0590 137 {
abougouffa 0:5311825d0590 138 if (intf_nb == gamepad_intf) {
abougouffa 0:5311825d0590 139 if (type == INTERRUPT_ENDPOINT && dir == IN) {
abougouffa 0:5311825d0590 140 gamepad_device_found = true;
abougouffa 0:5311825d0590 141 return true;
abougouffa 0:5311825d0590 142 }
abougouffa 0:5311825d0590 143 }
abougouffa 0:5311825d0590 144 return false;
abougouffa 0:5311825d0590 145 }
abougouffa 0:5311825d0590 146
abougouffa 0:5311825d0590 147 #endif