USB Mouse (relative) example for mbed NXP LPC11U24 beta
USB_HID_STACK/USBHID.c@1:e089be2a6aa1, 2011-11-09 (annotated)
- Committer:
- chris
- Date:
- Wed Nov 09 15:55:10 2011 +0000
- Revision:
- 1:e089be2a6aa1
- Parent:
- 0:163560051396
removed include for <math.h> that is already included by mbed.h
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
chris | 0:163560051396 | 1 | /* USBClass_HID.c */ |
chris | 0:163560051396 | 2 | /* Human Interface Device (HID) class */ |
chris | 0:163560051396 | 3 | /* Copyright (c) 2011 ARM Limited. All rights reserved. */ |
chris | 0:163560051396 | 4 | |
chris | 0:163560051396 | 5 | #include "stdint.h" |
chris | 0:163560051396 | 6 | |
chris | 0:163560051396 | 7 | #include "USBEndpoints.h" |
chris | 0:163560051396 | 8 | #include "USBDevice_Types.h" |
chris | 0:163560051396 | 9 | #include "USBBusInterface.h" |
chris | 0:163560051396 | 10 | #include "USBHID.h" |
chris | 0:163560051396 | 11 | |
chris | 0:163560051396 | 12 | static USBHID * instHID; |
chris | 0:163560051396 | 13 | |
chris | 0:163560051396 | 14 | /* Output report from SET_REPORT request */ |
chris | 0:163560051396 | 15 | static HID_REPORT outputReport; |
chris | 0:163560051396 | 16 | |
chris | 0:163560051396 | 17 | void setInstanceHID(USBHID * _inst){ instHID = _inst;}; |
chris | 0:163560051396 | 18 | |
chris | 0:163560051396 | 19 | bool USBClass_HID_request(void) |
chris | 0:163560051396 | 20 | { |
chris | 0:163560051396 | 21 | /* Called in ISR context */ |
chris | 0:163560051396 | 22 | |
chris | 0:163560051396 | 23 | bool success = false; |
chris | 0:163560051396 | 24 | CONTROL_TRANSFER *transfer = USBDevice_getTransferPtr(); |
chris | 0:163560051396 | 25 | uint8_t *hidDescriptor; |
chris | 0:163560051396 | 26 | |
chris | 0:163560051396 | 27 | /* Process additional standard requests */ |
chris | 0:163560051396 | 28 | |
chris | 0:163560051396 | 29 | if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE)) |
chris | 0:163560051396 | 30 | { |
chris | 0:163560051396 | 31 | switch (transfer->setup.bRequest) |
chris | 0:163560051396 | 32 | { |
chris | 0:163560051396 | 33 | case GET_DESCRIPTOR: |
chris | 0:163560051396 | 34 | switch (DESCRIPTOR_TYPE(transfer->setup.wValue)) |
chris | 0:163560051396 | 35 | { |
chris | 0:163560051396 | 36 | case REPORT_DESCRIPTOR: |
chris | 0:163560051396 | 37 | printf("get report descr\r\n"); |
chris | 0:163560051396 | 38 | if ((instHID->ReportDesc() != NULL) \ |
chris | 0:163560051396 | 39 | && (instHID->ReportDescLength() != 0)) |
chris | 0:163560051396 | 40 | { |
chris | 0:163560051396 | 41 | transfer->remaining = instHID->ReportDescLength(); |
chris | 0:163560051396 | 42 | transfer->ptr = instHID->ReportDesc(); |
chris | 0:163560051396 | 43 | transfer->direction = DEVICE_TO_HOST; |
chris | 0:163560051396 | 44 | success = true; |
chris | 0:163560051396 | 45 | } |
chris | 0:163560051396 | 46 | break; |
chris | 0:163560051396 | 47 | case HID_DESCRIPTOR: |
chris | 0:163560051396 | 48 | /* Find the HID descriptor, after the configuration descriptor */ |
chris | 0:163560051396 | 49 | hidDescriptor = USBDevice_findDescriptor(HID_DESCRIPTOR); |
chris | 0:163560051396 | 50 | if (hidDescriptor != NULL) /* NULL = Not found */ |
chris | 0:163560051396 | 51 | { |
chris | 0:163560051396 | 52 | transfer->remaining = HID_DESCRIPTOR_LENGTH; |
chris | 0:163560051396 | 53 | transfer->ptr = hidDescriptor; |
chris | 0:163560051396 | 54 | transfer->direction = DEVICE_TO_HOST; |
chris | 0:163560051396 | 55 | success = true; |
chris | 0:163560051396 | 56 | } |
chris | 0:163560051396 | 57 | break; |
chris | 0:163560051396 | 58 | |
chris | 0:163560051396 | 59 | default: |
chris | 0:163560051396 | 60 | break; |
chris | 0:163560051396 | 61 | } |
chris | 0:163560051396 | 62 | break; |
chris | 0:163560051396 | 63 | default: |
chris | 0:163560051396 | 64 | break; |
chris | 0:163560051396 | 65 | } |
chris | 0:163560051396 | 66 | } |
chris | 0:163560051396 | 67 | |
chris | 0:163560051396 | 68 | /* Process class-specific requests */ |
chris | 0:163560051396 | 69 | |
chris | 0:163560051396 | 70 | if (transfer->setup.bmRequestType.Type == CLASS_TYPE) |
chris | 0:163560051396 | 71 | { |
chris | 0:163560051396 | 72 | switch (transfer->setup.bRequest) |
chris | 0:163560051396 | 73 | { |
chris | 0:163560051396 | 74 | case SET_REPORT: |
chris | 0:163560051396 | 75 | /* First byte will be used for report ID */ |
chris | 0:163560051396 | 76 | outputReport.data[0] = transfer->setup.wValue & 0xff; |
chris | 0:163560051396 | 77 | outputReport.length = transfer->setup.wLength + 1; |
chris | 0:163560051396 | 78 | |
chris | 0:163560051396 | 79 | transfer->remaining = sizeof(outputReport.data) - 1; |
chris | 0:163560051396 | 80 | transfer->ptr = &outputReport.data[1]; |
chris | 0:163560051396 | 81 | transfer->direction = HOST_TO_DEVICE; |
chris | 0:163560051396 | 82 | transfer->notify = true; /* Callback on completion */ |
chris | 0:163560051396 | 83 | success = true; |
chris | 0:163560051396 | 84 | default: |
chris | 0:163560051396 | 85 | break; |
chris | 0:163560051396 | 86 | } |
chris | 0:163560051396 | 87 | } |
chris | 0:163560051396 | 88 | |
chris | 0:163560051396 | 89 | return success; |
chris | 0:163560051396 | 90 | } |
chris | 0:163560051396 | 91 | |
chris | 0:163560051396 | 92 | void USBClass_HID_requestCompleted(void) |
chris | 0:163560051396 | 93 | { |
chris | 0:163560051396 | 94 | /* SET_REPORT request - data is now valid */ |
chris | 0:163560051396 | 95 | |
chris | 0:163560051396 | 96 | instHID->HID_callbackSetReport(&outputReport); |
chris | 0:163560051396 | 97 | } |
chris | 0:163560051396 | 98 | |
chris | 0:163560051396 | 99 | bool USBClass_HID_sendInputReport(uint8_t endpoint, HID_REPORT *report) |
chris | 0:163560051396 | 100 | { |
chris | 0:163560051396 | 101 | EP_STATUS result; |
chris | 0:163560051396 | 102 | |
chris | 0:163560051396 | 103 | if (report->length > MAX_HID_REPORT_SIZE) |
chris | 0:163560051396 | 104 | { |
chris | 0:163560051396 | 105 | return false; |
chris | 0:163560051396 | 106 | } |
chris | 0:163560051396 | 107 | |
chris | 0:163560051396 | 108 | /* Block if not configured */ |
chris | 0:163560051396 | 109 | while (!USBDevice_isConfigured()); |
chris | 0:163560051396 | 110 | |
chris | 0:163560051396 | 111 | /* Send report */ |
chris | 0:163560051396 | 112 | result = USBBusInterface_endpointWrite(endpoint, report->data, report->length); |
chris | 0:163560051396 | 113 | |
chris | 0:163560051396 | 114 | if (result != EP_PENDING) |
chris | 0:163560051396 | 115 | { |
chris | 0:163560051396 | 116 | return false; |
chris | 0:163560051396 | 117 | } |
chris | 0:163560051396 | 118 | |
chris | 0:163560051396 | 119 | /* Wait for completion */ |
chris | 0:163560051396 | 120 | do { |
chris | 0:163560051396 | 121 | result = USBBusInterface_endpointWriteResult(endpoint); |
chris | 0:163560051396 | 122 | } while ((result == EP_PENDING) && USBDevice_isConfigured()); |
chris | 0:163560051396 | 123 | |
chris | 0:163560051396 | 124 | return (result == EP_COMPLETED); |
chris | 0:163560051396 | 125 | } |
chris | 0:163560051396 | 126 | |
chris | 0:163560051396 | 127 | #if 0 |
chris | 0:163560051396 | 128 | bool USBClass_HID_getOutputReport(uint8_t endpoint, HID_REPORT *report) |
chris | 0:163560051396 | 129 | { |
chris | 0:163560051396 | 130 | EP_RESULT result; |
chris | 0:163560051396 | 131 | uint32_t bytesRead = 0; |
chris | 0:163560051396 | 132 | |
chris | 0:163560051396 | 133 | /* Block if not configured */ |
chris | 0:163560051396 | 134 | while (!USBDevice_isConfigured()); |
chris | 0:163560051396 | 135 | |
chris | 0:163560051396 | 136 | /* Read report */ |
chris | 0:163560051396 | 137 | result = USBBusInterface_endpointRead(endpoint, report->data, MAX_HID_REPORT_SIZE); |
chris | 0:163560051396 | 138 | |
chris | 0:163560051396 | 139 | if (result != EP_PENDING) |
chris | 0:163560051396 | 140 | { |
chris | 0:163560051396 | 141 | return false; |
chris | 0:163560051396 | 142 | } |
chris | 0:163560051396 | 143 | |
chris | 0:163560051396 | 144 | /* Wait for completion */ |
chris | 0:163560051396 | 145 | do { |
chris | 0:163560051396 | 146 | result = USBBusInterface_endpointReadResult(endpoint, &bytesRead); |
chris | 0:163560051396 | 147 | } while ((result == EP_PENDING) && USBDevice_isConfigured()); |
chris | 0:163560051396 | 148 | |
chris | 0:163560051396 | 149 | report->length = bytesRead; |
chris | 0:163560051396 | 150 | |
chris | 0:163560051396 | 151 | return (result == EP_SUCCESS); |
chris | 0:163560051396 | 152 | } |
chris | 0:163560051396 | 153 | #endif |
chris | 0:163560051396 | 154 | |
chris | 0:163560051396 | 155 | |
chris | 0:163560051396 | 156 | #define DEFAULT_CONFIGURATION (1) |
chris | 0:163560051396 | 157 | |
chris | 0:163560051396 | 158 | USBHID::USBHID(){ |
chris | 0:163560051396 | 159 | setInstanceHID(this); |
chris | 0:163560051396 | 160 | USBDevice_init(); |
chris | 0:163560051396 | 161 | USBDevice_connect(); |
chris | 0:163560051396 | 162 | } |
chris | 0:163560051396 | 163 | |
chris | 0:163560051396 | 164 | uint16_t USBHID::ReportDescLength() { |
chris | 0:163560051396 | 165 | ReportDesc(); |
chris | 0:163560051396 | 166 | return reportLength; |
chris | 0:163560051396 | 167 | } |
chris | 0:163560051396 | 168 | |
chris | 0:163560051396 | 169 | /* |
chris | 0:163560051396 | 170 | * Route callbacks from lower layers to class(es) |
chris | 0:163560051396 | 171 | */ |
chris | 0:163560051396 | 172 | |
chris | 0:163560051396 | 173 | void USBHID::USBCallback_busReset(void) { |
chris | 0:163560051396 | 174 | /* Called in ISR context */ |
chris | 0:163560051396 | 175 | /* Called by USBDevice layer on bus reset */ |
chris | 0:163560051396 | 176 | |
chris | 0:163560051396 | 177 | /* May be used to reset state */ |
chris | 0:163560051396 | 178 | } |
chris | 0:163560051396 | 179 | |
chris | 0:163560051396 | 180 | bool USBHID::USBCallback_request() { |
chris | 0:163560051396 | 181 | /* Called in ISR context */ |
chris | 0:163560051396 | 182 | /* Called by USBDevice on Endpoint0 request */ |
chris | 0:163560051396 | 183 | |
chris | 0:163560051396 | 184 | /* This is used to handle extensions to standard requests */ |
chris | 0:163560051396 | 185 | /* and class specific requests. */ |
chris | 0:163560051396 | 186 | |
chris | 0:163560051396 | 187 | /* Return true if class handles this request */ |
chris | 0:163560051396 | 188 | return USBClass_HID_request(); |
chris | 0:163560051396 | 189 | } |
chris | 0:163560051396 | 190 | |
chris | 0:163560051396 | 191 | void USBHID::USBCallback_requestCompleted() { |
chris | 0:163560051396 | 192 | /* Called in ISR context */ |
chris | 0:163560051396 | 193 | /* Called by USBDevice on Endpoint0 request completion */ |
chris | 0:163560051396 | 194 | /* if the 'notify' flag has been set to true */ |
chris | 0:163560051396 | 195 | |
chris | 0:163560051396 | 196 | /* In this case it is used to indicate that a HID report has */ |
chris | 0:163560051396 | 197 | /* been received from the host on endpoint 0 */ |
chris | 0:163560051396 | 198 | |
chris | 0:163560051396 | 199 | USBClass_HID_requestCompleted(); |
chris | 0:163560051396 | 200 | } |
chris | 0:163560051396 | 201 | |
chris | 0:163560051396 | 202 | void USBHID::HID_callbackSetReport(HID_REPORT *report) { |
chris | 0:163560051396 | 203 | /* Called in ISR context */ |
chris | 0:163560051396 | 204 | |
chris | 0:163560051396 | 205 | /* HID Report received by SET_REPORT request */ |
chris | 0:163560051396 | 206 | /* First byte of data will be the report ID */ |
chris | 0:163560051396 | 207 | } |
chris | 0:163560051396 | 208 | |
chris | 0:163560051396 | 209 | bool USBHID::USBCallback_setConfiguration(uint8_t configuration) { |
chris | 0:163560051396 | 210 | /* Called in ISR context */ |
chris | 0:163560051396 | 211 | |
chris | 0:163560051396 | 212 | /* Set configuration. Return false if the */ |
chris | 0:163560051396 | 213 | /* configuration is not supported. */ |
chris | 0:163560051396 | 214 | if (configuration != DEFAULT_CONFIGURATION) { |
chris | 0:163560051396 | 215 | return false; |
chris | 0:163560051396 | 216 | } |
chris | 0:163560051396 | 217 | |
chris | 0:163560051396 | 218 | /* Configure endpoints > 0 */ |
chris | 0:163560051396 | 219 | USBDevice_addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT); |
chris | 0:163560051396 | 220 | return true; |
chris | 0:163560051396 | 221 | } |
chris | 0:163560051396 | 222 |