Repository for import to local machine
Dependencies: DMBasicGUI DMSupport
USBHostGC.cpp@0:47c880c1463d, 2016-01-13 (annotated)
- Committer:
- jmitc91516
- Date:
- Wed Jan 13 13:17:05 2016 +0000
- Revision:
- 0:47c880c1463d
- Child:
- 1:a5258871b33d
First revision of 5 inch display version of GC500_2. Dated 13 Jan 2016
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jmitc91516 | 0:47c880c1463d | 1 | /** |
jmitc91516 | 0:47c880c1463d | 2 | * A class to communicate with a USB GC. |
jmitc91516 | 0:47c880c1463d | 3 | * |
jmitc91516 | 0:47c880c1463d | 4 | * *** Important note - when reading data from the USB device, you must do this into memory allocated using *** |
jmitc91516 | 0:47c880c1463d | 5 | * *** the 'getSafeMem' function of the USBHost class. If you read it into 'normal' memory, your code will crash. *** |
jmitc91516 | 0:47c880c1463d | 6 | * *** This is my experience so far, at least. This applies, e.g. to all the 'Get...' functions below. *** |
jmitc91516 | 0:47c880c1463d | 7 | * *** (There may, of course, be a simple explanation for this, but if so, I am not currently aware of it.) *** |
jmitc91516 | 0:47c880c1463d | 8 | * *** This is why (currently) all the 'Get...' functions allocate a buffer from safe memory, *** |
jmitc91516 | 0:47c880c1463d | 9 | * *** read the data into it, then copy the data into the buffer provided by the caller. *** |
jmitc91516 | 0:47c880c1463d | 10 | */ |
jmitc91516 | 0:47c880c1463d | 11 | |
jmitc91516 | 0:47c880c1463d | 12 | #include "USBHostGC.h" |
jmitc91516 | 0:47c880c1463d | 13 | |
jmitc91516 | 0:47c880c1463d | 14 | extern void EasyGUIDebugPrint(char *stuffToPrint, short X, short Y); |
jmitc91516 | 0:47c880c1463d | 15 | |
jmitc91516 | 0:47c880c1463d | 16 | |
jmitc91516 | 0:47c880c1463d | 17 | USBHostGC::USBHostGC() |
jmitc91516 | 0:47c880c1463d | 18 | { |
jmitc91516 | 0:47c880c1463d | 19 | debugWindow = NULL; |
jmitc91516 | 0:47c880c1463d | 20 | |
jmitc91516 | 0:47c880c1463d | 21 | usbHost = USBHost::getHostInst(); |
jmitc91516 | 0:47c880c1463d | 22 | |
jmitc91516 | 0:47c880c1463d | 23 | reportBuffer = NULL; |
jmitc91516 | 0:47c880c1463d | 24 | |
jmitc91516 | 0:47c880c1463d | 25 | NoDeviceConnected(); // So far... |
jmitc91516 | 0:47c880c1463d | 26 | |
jmitc91516 | 0:47c880c1463d | 27 | alreadyInSetDeviceReport = false; |
jmitc91516 | 0:47c880c1463d | 28 | } |
jmitc91516 | 0:47c880c1463d | 29 | |
jmitc91516 | 0:47c880c1463d | 30 | USBHostGC::~USBHostGC() |
jmitc91516 | 0:47c880c1463d | 31 | { |
jmitc91516 | 0:47c880c1463d | 32 | NoDeviceConnected(); |
jmitc91516 | 0:47c880c1463d | 33 | } |
jmitc91516 | 0:47c880c1463d | 34 | |
jmitc91516 | 0:47c880c1463d | 35 | void USBHostGC::NoDeviceConnected(void) |
jmitc91516 | 0:47c880c1463d | 36 | { |
jmitc91516 | 0:47c880c1463d | 37 | deviceIsGC = false; |
jmitc91516 | 0:47c880c1463d | 38 | intfGC = -1; |
jmitc91516 | 0:47c880c1463d | 39 | intInEndpointGC = NULL; |
jmitc91516 | 0:47c880c1463d | 40 | usbGCDeviceConnected = NULL; |
jmitc91516 | 0:47c880c1463d | 41 | |
jmitc91516 | 0:47c880c1463d | 42 | if (reportBuffer != NULL) { |
jmitc91516 | 0:47c880c1463d | 43 | usbHost->returnSafeMem(reportBuffer); |
jmitc91516 | 0:47c880c1463d | 44 | reportBuffer = NULL; |
jmitc91516 | 0:47c880c1463d | 45 | } |
jmitc91516 | 0:47c880c1463d | 46 | } |
jmitc91516 | 0:47c880c1463d | 47 | |
jmitc91516 | 0:47c880c1463d | 48 | void USBHostGC::DebugPrint(const char* debugText) |
jmitc91516 | 0:47c880c1463d | 49 | { |
jmitc91516 | 0:47c880c1463d | 50 | if(debugWindow != NULL) { |
jmitc91516 | 0:47c880c1463d | 51 | swim_put_text(debugWindow, debugText); |
jmitc91516 | 0:47c880c1463d | 52 | } |
jmitc91516 | 0:47c880c1463d | 53 | } |
jmitc91516 | 0:47c880c1463d | 54 | |
jmitc91516 | 0:47c880c1463d | 55 | void USBHostGC::AllocateReportBuffer(void) |
jmitc91516 | 0:47c880c1463d | 56 | { |
jmitc91516 | 0:47c880c1463d | 57 | int reportSize = GC_MESSAGE_LENGTH; |
jmitc91516 | 0:47c880c1463d | 58 | |
jmitc91516 | 0:47c880c1463d | 59 | if (intInEndpointGC != NULL) { |
jmitc91516 | 0:47c880c1463d | 60 | int intInEndpointSize = intInEndpointGC->getSize(); |
jmitc91516 | 0:47c880c1463d | 61 | if (intInEndpointSize > reportSize) { |
jmitc91516 | 0:47c880c1463d | 62 | reportSize = intInEndpointSize; |
jmitc91516 | 0:47c880c1463d | 63 | } |
jmitc91516 | 0:47c880c1463d | 64 | } |
jmitc91516 | 0:47c880c1463d | 65 | |
jmitc91516 | 0:47c880c1463d | 66 | reportBuffer = usbHost->getSafeMem(reportSize); |
jmitc91516 | 0:47c880c1463d | 67 | } |
jmitc91516 | 0:47c880c1463d | 68 | |
jmitc91516 | 0:47c880c1463d | 69 | bool USBHostGC::AttachGCDevice(USBDeviceConnected* usbDeviceConnected) |
jmitc91516 | 0:47c880c1463d | 70 | { |
jmitc91516 | 0:47c880c1463d | 71 | intInEndpointGC = usbDeviceConnected->getEndpoint(intfGC, INTERRUPT_ENDPOINT, IN); |
jmitc91516 | 0:47c880c1463d | 72 | if (!intInEndpointGC) { |
jmitc91516 | 0:47c880c1463d | 73 | DebugPrint("AttachGCDevice - interrupt endpoint in not found - returning false\n"); |
jmitc91516 | 0:47c880c1463d | 74 | NoDeviceConnected(); |
jmitc91516 | 0:47c880c1463d | 75 | return false; |
jmitc91516 | 0:47c880c1463d | 76 | } |
jmitc91516 | 0:47c880c1463d | 77 | |
jmitc91516 | 0:47c880c1463d | 78 | usbDeviceConnected->setName("GC", intfGC); |
jmitc91516 | 0:47c880c1463d | 79 | |
jmitc91516 | 0:47c880c1463d | 80 | usbHost->registerDriver(usbDeviceConnected, intfGC, this, &USBHostGC::NoDeviceConnected); |
jmitc91516 | 0:47c880c1463d | 81 | |
jmitc91516 | 0:47c880c1463d | 82 | intInEndpointGC->attach(this, &USBHostGC::RXHandler); |
jmitc91516 | 0:47c880c1463d | 83 | |
jmitc91516 | 0:47c880c1463d | 84 | if (reportBuffer == NULL) { |
jmitc91516 | 0:47c880c1463d | 85 | AllocateReportBuffer(); |
jmitc91516 | 0:47c880c1463d | 86 | } |
jmitc91516 | 0:47c880c1463d | 87 | |
jmitc91516 | 0:47c880c1463d | 88 | usbHost->interruptRead(usbDeviceConnected, intInEndpointGC, reportBuffer, intInEndpointGC->getSize(), false); |
jmitc91516 | 0:47c880c1463d | 89 | |
jmitc91516 | 0:47c880c1463d | 90 | usbGCDeviceConnected = usbDeviceConnected; |
jmitc91516 | 0:47c880c1463d | 91 | |
jmitc91516 | 0:47c880c1463d | 92 | return true; |
jmitc91516 | 0:47c880c1463d | 93 | } |
jmitc91516 | 0:47c880c1463d | 94 | |
jmitc91516 | 0:47c880c1463d | 95 | void USBHostGC::RXHandler(void) |
jmitc91516 | 0:47c880c1463d | 96 | { |
jmitc91516 | 0:47c880c1463d | 97 | responseReceived = true; |
jmitc91516 | 0:47c880c1463d | 98 | |
jmitc91516 | 0:47c880c1463d | 99 | if (usbGCDeviceConnected) { |
jmitc91516 | 0:47c880c1463d | 100 | usbHost->interruptRead(usbGCDeviceConnected, intInEndpointGC, reportBuffer, intInEndpointGC->getSize(), false); |
jmitc91516 | 0:47c880c1463d | 101 | } |
jmitc91516 | 0:47c880c1463d | 102 | } |
jmitc91516 | 0:47c880c1463d | 103 | |
jmitc91516 | 0:47c880c1463d | 104 | bool USBHostGC::ExecutingSetDeviceReport(void) |
jmitc91516 | 0:47c880c1463d | 105 | { |
jmitc91516 | 0:47c880c1463d | 106 | return alreadyInSetDeviceReport; |
jmitc91516 | 0:47c880c1463d | 107 | } |
jmitc91516 | 0:47c880c1463d | 108 | |
jmitc91516 | 0:47c880c1463d | 109 | USB_TYPE USBHostGC::SetDeviceReport(USBDeviceConnected * dev, const char* report, char* response) |
jmitc91516 | 0:47c880c1463d | 110 | { |
jmitc91516 | 0:47c880c1463d | 111 | // Neither this function, nor the GC itself, are re-entrant... |
jmitc91516 | 0:47c880c1463d | 112 | if(alreadyInSetDeviceReport) { |
jmitc91516 | 0:47c880c1463d | 113 | return USB_TYPE_PROCESSING; |
jmitc91516 | 0:47c880c1463d | 114 | } |
jmitc91516 | 0:47c880c1463d | 115 | |
jmitc91516 | 0:47c880c1463d | 116 | alreadyInSetDeviceReport = true; |
jmitc91516 | 0:47c880c1463d | 117 | |
jmitc91516 | 0:47c880c1463d | 118 | if (reportBuffer == NULL) { |
jmitc91516 | 0:47c880c1463d | 119 | AllocateReportBuffer(); |
jmitc91516 | 0:47c880c1463d | 120 | } |
jmitc91516 | 0:47c880c1463d | 121 | |
jmitc91516 | 0:47c880c1463d | 122 | int i; |
jmitc91516 | 0:47c880c1463d | 123 | for (i = 0; (i < GC_MESSAGE_LENGTH) && (report[i]); ++i) { |
jmitc91516 | 0:47c880c1463d | 124 | reportBuffer[i] = (uint8_t) report[i]; |
jmitc91516 | 0:47c880c1463d | 125 | } |
jmitc91516 | 0:47c880c1463d | 126 | //reportBuffer[i++] = (uint8_t) GC_CR; // Append <CR> - make *sure* it is the same code the GC expects |
jmitc91516 | 0:47c880c1463d | 127 | // Fill remainder of buffer with nulls, to pad out to 10 bytes |
jmitc91516 | 0:47c880c1463d | 128 | for ( ; i < GC_MESSAGE_LENGTH; ++i) { |
jmitc91516 | 0:47c880c1463d | 129 | reportBuffer[i] = 0; |
jmitc91516 | 0:47c880c1463d | 130 | } |
jmitc91516 | 0:47c880c1463d | 131 | //reportBuffer[GC_MESSAGE_LENGTH - 1] = (uint8_t) GC_CR; |
jmitc91516 | 0:47c880c1463d | 132 | |
jmitc91516 | 0:47c880c1463d | 133 | responseReceived = false; // Synchronise with RXHandler |
jmitc91516 | 0:47c880c1463d | 134 | |
jmitc91516 | 0:47c880c1463d | 135 | //EasyGUIDebugPrint("SetDeviceReport - before controlWrite", 20,80); |
jmitc91516 | 0:47c880c1463d | 136 | USB_TYPE t = usbHost->controlWrite( dev, |
jmitc91516 | 0:47c880c1463d | 137 | 1, // Non-zero - tells GC - set report, not set configuration |
jmitc91516 | 0:47c880c1463d | 138 | SET_CONFIGURATION, |
jmitc91516 | 0:47c880c1463d | 139 | 0, |
jmitc91516 | 0:47c880c1463d | 140 | 0, reportBuffer, GC_MESSAGE_LENGTH); |
jmitc91516 | 0:47c880c1463d | 141 | //EasyGUIDebugPrint("SetDeviceReport - after controlWrite", 20,100); |
jmitc91516 | 0:47c880c1463d | 142 | |
jmitc91516 | 0:47c880c1463d | 143 | while (!responseReceived) { |
jmitc91516 | 0:47c880c1463d | 144 | // wait... |
jmitc91516 | 0:47c880c1463d | 145 | } |
jmitc91516 | 0:47c880c1463d | 146 | |
jmitc91516 | 0:47c880c1463d | 147 | //EasyGUIDebugPrint("SetDeviceReport - after wait for response", 20,120); |
jmitc91516 | 0:47c880c1463d | 148 | |
jmitc91516 | 0:47c880c1463d | 149 | // RXHandler has now received the response - return it to the caller |
jmitc91516 | 0:47c880c1463d | 150 | |
jmitc91516 | 0:47c880c1463d | 151 | for (i = 0; i < GC_MESSAGE_LENGTH; ++i) { |
jmitc91516 | 0:47c880c1463d | 152 | response[i] = reportBuffer[i]; |
jmitc91516 | 0:47c880c1463d | 153 | } |
jmitc91516 | 0:47c880c1463d | 154 | response[i] = '\0'; |
jmitc91516 | 0:47c880c1463d | 155 | |
jmitc91516 | 0:47c880c1463d | 156 | alreadyInSetDeviceReport = false; |
jmitc91516 | 0:47c880c1463d | 157 | |
jmitc91516 | 0:47c880c1463d | 158 | return t; |
jmitc91516 | 0:47c880c1463d | 159 | } |
jmitc91516 | 0:47c880c1463d | 160 | |
jmitc91516 | 0:47c880c1463d | 161 | // Part of IUSBEnumerator interface |
jmitc91516 | 0:47c880c1463d | 162 | /* virtual */ void USBHostGC::setVidPid(uint16_t vid, uint16_t pid) |
jmitc91516 | 0:47c880c1463d | 163 | { |
jmitc91516 | 0:47c880c1463d | 164 | char buff[100]; |
jmitc91516 | 0:47c880c1463d | 165 | sprintf(buff, "setVidPid(%d %X, %d %X)\n", vid, vid, pid, pid); |
jmitc91516 | 0:47c880c1463d | 166 | DebugPrint(buff); |
jmitc91516 | 0:47c880c1463d | 167 | |
jmitc91516 | 0:47c880c1463d | 168 | deviceIsGC = ((vid == GC_VENDOR_ID) && (pid == GC_PRODUCT_ID)); |
jmitc91516 | 0:47c880c1463d | 169 | |
jmitc91516 | 0:47c880c1463d | 170 | DebugPrint(deviceIsGC ? "Device is a GC\n" : "Device is *not* a GC\n"); |
jmitc91516 | 0:47c880c1463d | 171 | } |
jmitc91516 | 0:47c880c1463d | 172 | |
jmitc91516 | 0:47c880c1463d | 173 | // Part of IUSBEnumerator interface - must return true if the interface should be parsed |
jmitc91516 | 0:47c880c1463d | 174 | /* virtual */ bool USBHostGC::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) |
jmitc91516 | 0:47c880c1463d | 175 | { |
jmitc91516 | 0:47c880c1463d | 176 | char buff[100]; |
jmitc91516 | 0:47c880c1463d | 177 | sprintf(buff, "parseInterface(%d %X, %d %X, %d %X, %d %X)\n", intf_nb, intf_nb, intf_class, intf_class, intf_subclass, intf_subclass, intf_protocol, intf_protocol); |
jmitc91516 | 0:47c880c1463d | 178 | DebugPrint(buff); |
jmitc91516 | 0:47c880c1463d | 179 | |
jmitc91516 | 0:47c880c1463d | 180 | // setVidPid should have been called before this - |
jmitc91516 | 0:47c880c1463d | 181 | // assume it will have identified whether or not the device is a GC |
jmitc91516 | 0:47c880c1463d | 182 | if (deviceIsGC) { |
jmitc91516 | 0:47c880c1463d | 183 | if ((intfGC == -1) && |
jmitc91516 | 0:47c880c1463d | 184 | (intf_class == HID_CLASS)) { |
jmitc91516 | 0:47c880c1463d | 185 | // Don't care about subclass and protocol in this case |
jmitc91516 | 0:47c880c1463d | 186 | |
jmitc91516 | 0:47c880c1463d | 187 | intfGC = intf_nb; |
jmitc91516 | 0:47c880c1463d | 188 | DebugPrint(" **** GC found **** \n"); |
jmitc91516 | 0:47c880c1463d | 189 | } |
jmitc91516 | 0:47c880c1463d | 190 | DebugPrint("GC found - parseInterface returning true\n"); |
jmitc91516 | 0:47c880c1463d | 191 | return true; |
jmitc91516 | 0:47c880c1463d | 192 | } |
jmitc91516 | 0:47c880c1463d | 193 | |
jmitc91516 | 0:47c880c1463d | 194 | DebugPrint("No GC found - parseInterface returning false\n"); |
jmitc91516 | 0:47c880c1463d | 195 | return false; |
jmitc91516 | 0:47c880c1463d | 196 | } |
jmitc91516 | 0:47c880c1463d | 197 | |
jmitc91516 | 0:47c880c1463d | 198 | // Part of IUSBEnumerator interface - must return true if the endpoint will be used |
jmitc91516 | 0:47c880c1463d | 199 | /* virtual */ bool USBHostGC::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) |
jmitc91516 | 0:47c880c1463d | 200 | { |
jmitc91516 | 0:47c880c1463d | 201 | char buff[100]; |
jmitc91516 | 0:47c880c1463d | 202 | sprintf(buff, "useEndPoint(%d %X, %d %X, %d %X)\n", intf_nb, intf_nb, type, type, dir, dir); |
jmitc91516 | 0:47c880c1463d | 203 | DebugPrint(buff); |
jmitc91516 | 0:47c880c1463d | 204 | |
jmitc91516 | 0:47c880c1463d | 205 | if (deviceIsGC) { |
jmitc91516 | 0:47c880c1463d | 206 | if ((intfGC == intf_nb) && |
jmitc91516 | 0:47c880c1463d | 207 | (type == INTERRUPT_ENDPOINT) && |
jmitc91516 | 0:47c880c1463d | 208 | (dir == IN)) { |
jmitc91516 | 0:47c880c1463d | 209 | DebugPrint("GC endpoint found - useEndPoint returning true\n"); |
jmitc91516 | 0:47c880c1463d | 210 | return true; |
jmitc91516 | 0:47c880c1463d | 211 | } |
jmitc91516 | 0:47c880c1463d | 212 | } |
jmitc91516 | 0:47c880c1463d | 213 | |
jmitc91516 | 0:47c880c1463d | 214 | // 'else' |
jmitc91516 | 0:47c880c1463d | 215 | DebugPrint("GC endpoint not found - useEndpoint returning false\n"); |
jmitc91516 | 0:47c880c1463d | 216 | return false; |
jmitc91516 | 0:47c880c1463d | 217 | } |