Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHID.c Source File

USBHID.c

00001 /* USBClass_HID.c */
00002 /* Human Interface Device (HID) class */
00003 /* Copyright (c) 2011 ARM Limited. All rights reserved. */
00004 
00005 #include "stdint.h"
00006 
00007 #include "USBEndpoints.h"
00008 #include "USBDevice_Types.h"
00009 #include "USBBusInterface.h"
00010 #include "USBHID.h"
00011 
00012 static USBHID * instHID;
00013 
00014 /* Output report from SET_REPORT request */
00015 static HID_REPORT outputReport;
00016 
00017 void setInstanceHID(USBHID * _inst){ instHID = _inst;};
00018 
00019 bool USBClass_HID_request(void)
00020 {
00021     /* Called in ISR context */
00022 
00023     bool success = false;
00024     CONTROL_TRANSFER *transfer = USBDevice_getTransferPtr();
00025     uint8_t *hidDescriptor;
00026 
00027     /* Process additional standard requests */
00028 
00029     if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
00030     {
00031         switch (transfer->setup.bRequest)
00032         {
00033             case GET_DESCRIPTOR:
00034                 switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
00035                 {
00036                     case REPORT_DESCRIPTOR:
00037                         printf("get report descr\r\n");
00038                         if ((instHID->ReportDesc() != NULL) \
00039                             && (instHID->ReportDescLength() != 0))
00040                         {
00041                             transfer->remaining = instHID->ReportDescLength();
00042                             transfer->ptr = instHID->ReportDesc();
00043                             transfer->direction = DEVICE_TO_HOST;
00044                             success = true;
00045                         }
00046                         break;
00047                     case HID_DESCRIPTOR:
00048                             /* Find the HID descriptor, after the configuration descriptor */
00049                             hidDescriptor = USBDevice_findDescriptor(HID_DESCRIPTOR);
00050                             if (hidDescriptor != NULL) /* NULL = Not found */
00051                             {
00052                                 transfer->remaining = HID_DESCRIPTOR_LENGTH;
00053                                 transfer->ptr = hidDescriptor;
00054                                 transfer->direction = DEVICE_TO_HOST;
00055                                 success = true;
00056                             }
00057                             break;
00058                      
00059                     default:
00060                         break;
00061                 }
00062                 break;
00063             default:
00064                 break;
00065         }
00066     }
00067 
00068     /* Process class-specific requests */
00069 
00070     if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
00071     {
00072         switch (transfer->setup.bRequest)
00073         {
00074              case SET_REPORT:
00075                 /* First byte will be used for report ID */
00076                 outputReport.data[0] = transfer->setup.wValue & 0xff;
00077                 outputReport.length = transfer->setup.wLength + 1;
00078 
00079                 transfer->remaining = sizeof(outputReport.data) - 1;
00080                 transfer->ptr = &outputReport.data[1];
00081                 transfer->direction = HOST_TO_DEVICE;
00082                 transfer->notify = true; /* Callback on completion */
00083                 success = true;
00084             default:
00085                 break;
00086         }
00087     }
00088 
00089     return success;
00090 }
00091 
00092 void USBClass_HID_requestCompleted(void)
00093 {
00094     /* SET_REPORT request - data is now valid */
00095 
00096     instHID->HID_callbackSetReport(&outputReport);
00097 }
00098 
00099 bool USBClass_HID_sendInputReport(uint8_t endpoint, HID_REPORT *report)
00100 {
00101     EP_STATUS result;
00102 
00103     if (report->length > MAX_HID_REPORT_SIZE)
00104     {
00105         return false;
00106     }
00107 
00108     /* Block if not configured */
00109     while (!USBDevice_isConfigured());
00110     
00111     /* Send report */
00112     result = USBBusInterface_endpointWrite(endpoint, report->data, report->length);
00113 
00114     if (result != EP_PENDING)
00115     {
00116         return false;
00117     }
00118 
00119     /* Wait for completion */
00120     do {
00121         result = USBBusInterface_endpointWriteResult(endpoint);
00122     } while ((result == EP_PENDING) && USBDevice_isConfigured());
00123 
00124     return (result == EP_COMPLETED);
00125 }
00126 
00127 #if 0
00128 bool USBClass_HID_getOutputReport(uint8_t endpoint, HID_REPORT *report)
00129 {
00130     EP_RESULT result;
00131     uint32_t bytesRead = 0;
00132 
00133     /* Block if not configured */
00134     while (!USBDevice_isConfigured());
00135 
00136     /* Read report */
00137     result = USBBusInterface_endpointRead(endpoint, report->data, MAX_HID_REPORT_SIZE);
00138 
00139     if (result != EP_PENDING)
00140     {
00141         return false;
00142     }
00143 
00144     /* Wait for completion */
00145     do {
00146         result = USBBusInterface_endpointReadResult(endpoint, &bytesRead);
00147     } while ((result == EP_PENDING) && USBDevice_isConfigured());
00148 
00149     report->length = bytesRead;
00150 
00151     return (result == EP_SUCCESS);
00152 }
00153 #endif
00154 
00155 
00156 #define DEFAULT_CONFIGURATION (1)
00157 
00158 USBHID::USBHID(){
00159     setInstanceHID(this);
00160     USBDevice_init(); 
00161     USBDevice_connect();
00162 }
00163 
00164 uint16_t USBHID::ReportDescLength() {
00165     ReportDesc(); 
00166     return reportLength;
00167 }
00168 
00169 /*
00170  *  Route callbacks from lower layers to class(es)
00171  */
00172 
00173 void USBHID::USBCallback_busReset(void) {
00174     /* Called in ISR context */
00175     /* Called by USBDevice layer on bus reset */
00176 
00177     /* May be used to reset state */
00178 }
00179 
00180 bool USBHID::USBCallback_request() {
00181     /* Called in ISR context */
00182     /* Called by USBDevice on Endpoint0 request */
00183 
00184     /* This is used to handle extensions to standard requests */
00185     /* and class specific requests. */
00186 
00187     /* Return true if class handles this request */
00188     return USBClass_HID_request();
00189 }
00190 
00191 void USBHID::USBCallback_requestCompleted() {
00192     /* Called in ISR context */
00193     /* Called by USBDevice on Endpoint0 request completion */
00194     /* if the 'notify' flag has been set to true */
00195 
00196     /* In this case it is used to indicate that a HID report has */
00197     /* been received from the host on endpoint 0 */
00198 
00199     USBClass_HID_requestCompleted();
00200 }
00201 
00202 void USBHID::HID_callbackSetReport(HID_REPORT *report) {
00203     /* Called in ISR context */
00204 
00205     /* HID Report received by SET_REPORT request */
00206     /* First byte of data will be the report ID */
00207 }
00208 
00209 bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
00210     /* Called in ISR context */
00211 
00212     /* Set configuration. Return false if the */
00213     /* configuration is not supported. */
00214     if (configuration != DEFAULT_CONFIGURATION) {
00215         return false;
00216     }
00217 
00218     /* Configure endpoints > 0 */
00219     USBDevice_addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
00220     return true;
00221 }
00222