SAM3S8/SD8 Software Package: examples_usb/usb_hid_transfer/HIDTest/report.c Source File

SAM3S8/SD8 Software Package 1.2

# report.c

    00001 /*++
    00002
    00003 Copyright (c) 1996    Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     report.c
    00008
    00009 Abstract:
    00010
    00011     This module contains the code for reading/writing hid reports and
    00012     translating those HID reports into useful information.
    00013
    00014 Environment:
    00015
    00016     User mode
    00017
    00018 --*/
    00019
    00020 #include <stdlib.h>
    00021 #include <wtypes.h>
    00022 #include "hidsdi.h"
    00023 #include "hid.h"
    00024
    00025 BOOLEAN
    00026 UnpackReport (
    00027    IN       PCHAR                ReportBuffer,
    00028    IN       USHORT               ReportBufferLength,
    00029    IN       HIDP_REPORT_TYPE     ReportType,
    00030    IN OUT   PHID_DATA            Data,
    00031    IN       ULONG                DataLength,
    00032    IN       PHIDP_PREPARSED_DATA Ppd
    00033    );
    00034
    00035 BOOLEAN
    00036 PackReport (
    00037    OUT      PCHAR                ReportBuffer,
    00038    IN       USHORT               ReportBufferLength,
    00039    IN       HIDP_REPORT_TYPE     ReportType,
    00040    IN       PHID_DATA            Data,
    00041    IN       ULONG                DataLength,
    00042    IN       PHIDP_PREPARSED_DATA Ppd
    00043    );
    00044
    00045 BOOLEAN
    00046 Read (
    00047    PHID_DEVICE    HidDevice
    00048    )
    00049 /*++
    00050 RoutineDescription:
    00051    Given a struct _HID_DEVICE, obtain a read report and unpack the values
    00052    into the InputData array.
    00053 --*/
    00054 {
    00055     DWORD    bytesRead;
    00056
    00057     if (!ReadFile (HidDevice->HidDevice,
    00058                   HidDevice->InputReportBuffer,
    00059                   HidDevice->Caps.InputReportByteLength,
    00060                   &bytesRead,
    00061                   NULL))
    00062     {
    00063         return FALSE;
    00064     }
    00065
    00066     ASSERT (bytesRead == HidDevice->Caps.InputReportByteLength);
    00067     if (bytesRead != HidDevice->Caps.InputReportByteLength)
    00068     {
    00069         return FALSE;
    00070     }
    00071
    00072     return UnpackReport (HidDevice->InputReportBuffer,
    00073                          HidDevice->Caps.InputReportByteLength,
    00074                          HidP_Input,
    00075                          HidDevice->InputData,
    00076                          HidDevice->InputDataLength,
    00077                          HidDevice->Ppd);
    00078 }
    00079
    00080 BOOLEAN
    00081 ReadOverlapped (
    00082     PHID_DEVICE     HidDevice,
    00083     HANDLE          CompletionEvent
    00084    )
    00085 /*++
    00086 RoutineDescription:
    00087    Given a struct _HID_DEVICE, obtain a read report and unpack the values
    00088    into the InputData array.
    00089 --*/
    00090 {
    00091     static OVERLAPPED  overlap;
    00092     DWORD       bytesRead;
    00093     BOOL        readStatus;
    00094
    00095     /*
    00096     // Setup the overlap structure using the completion event passed in to
    00097     //  to use for signalling the completion of the Read
    00098     */
    00099
    00100     memset(&overlap, 0, sizeof(OVERLAPPED));
    00101
    00102     overlap.hEvent = CompletionEvent;
    00103
    00104     /*
    00105     // Execute the read call saving the return code to determine how to
    00106     //  proceed (ie. the read completed synchronously or not).
    00107     */
    00108
    00109     readStatus = ReadFile ( HidDevice -> HidDevice,
    00110                             HidDevice -> InputReportBuffer,
    00111                             HidDevice -> Caps.InputReportByteLength,
    00112                             &bytesRead,
    00113                             &overlap);
    00114
    00115     /*
    00116     // If the readStatus is FALSE, then one of two cases occurred.
    00117     //  1) ReadFile call succeeded but the Read is an overlapped one.  Here,
    00118     //      we should return TRUE to indicate that the Read succeeded.  However,
    00119     //      the calling thread should be blocked on the completion event
    00120     //      which means it won't continue until the read actually completes
    00121     //
    00122     //  2) The ReadFile call failed for some unknown reason...In this case,
    00123     //      the return code will be FALSE
    00124     */
    00125
    00126     if (!readStatus)
    00127     {
    00128         return (ERROR_IO_PENDING == GetLastError());
    00129     }
    00130
    00131     /*
    00132     // If readStatus is TRUE, then the ReadFile call completed synchronously,
    00133     //   since the calling thread is probably going to wait on the completion
    00134     //   event, signal the event so it knows it can continue.
    00135     */
    00136
    00137     else
    00138     {
    00139         SetEvent(CompletionEvent);
    00140         return (TRUE);
    00141     }
    00142 }
    00143
    00144 BOOLEAN
    00145 Write (
    00146    PHID_DEVICE    HidDevice
    00147 )
    00148 /*++
    00149 RoutineDescription:
    00150    Given a struct _HID_DEVICE, take the information in the HID_DATA array
    00151    pack it into multiple write reports and send each report to the HID device
    00152 --*/
    00153 {
    00154     DWORD     bytesWritten;
    00155     PHID_DATA pData;
    00156     ULONG     Index;
    00157     BOOLEAN   Status;
    00158     BOOLEAN   WriteStatus;
    00159
    00160     /*
    00161     // Begin by looping through the HID_DEVICE's HID_DATA structure and setting
    00162     //   the IsDataSet field to FALSE to indicate that each structure has
    00163     //   not yet been set for this Write call.
    00164     */
    00165
    00166     pData = HidDevice -> OutputData;
    00167
    00168     for (Index = 0; Index < HidDevice -> OutputDataLength; Index++, pData++)
    00169     {
    00170         pData -> IsDataSet = FALSE;
    00171     }
    00172
    00173     /*
    00174     // In setting all the data in the reports, we need to pack a report buffer
    00175     //   and call WriteFile for each report ID that is represented by the
    00176     //   device structure.  To do so, the IsDataSet field will be used to
    00177     //   determine if a given report field has already been set.
    00178     */
    00179
    00180     Status = TRUE;
    00181
    00182     pData = HidDevice -> OutputData;
    00183     for (Index = 0; Index < HidDevice -> OutputDataLength; Index++, pData++)
    00184     {
    00185
    00186         if (!pData -> IsDataSet)
    00187         {
    00188             /*
    00189             // Package the report for this data structure.  PackReport will
    00190             //    set the IsDataSet fields of this structure and any other
    00191             //    structures that it includes in the report with this structure
    00192             */
    00193
    00194             PackReport (HidDevice->OutputReportBuffer,
    00195                      HidDevice->Caps.OutputReportByteLength,
    00196                      HidP_Output,
    00197                      pData,
    00198                      HidDevice->OutputDataLength - Index,
    00199                      HidDevice->Ppd);
    00200
    00201             /*
    00202             // Now a report has been packaged up...Send it down to the device
    00203             */
    00204
    00205             WriteStatus = WriteFile (HidDevice->HidDevice,
    00206                                   HidDevice->OutputReportBuffer,
    00207                                   HidDevice->Caps.OutputReportByteLength,
    00208                                   &bytesWritten,
    00209                                   NULL) && (bytesWritten == HidDevice -> Caps.OutputReportByteLength);
    00210
    00211             Status = Status && WriteStatus;
    00212         }
    00213     }
    00214     return (Status);
    00215 }
    00216
    00217 BOOLEAN
    00218 SetFeature (
    00219     PHID_DEVICE    HidDevice
    00220 )
    00221 /*++
    00222 RoutineDescription:
    00223 Given a struct _HID_DEVICE, take the information in the HID_DATA array
    00224 pack it into multiple reports and send it to the hid device via HidD_SetFeature()
    00225 --*/
    00226 {
    00227     PHID_DATA pData;
    00228     ULONG     Index;
    00229     BOOLEAN   Status;
    00230     BOOLEAN   FeatureStatus;
    00231     /*
    00232     // Begin by looping through the HID_DEVICE's HID_DATA structure and setting
    00233     //   the IsDataSet field to FALSE to indicate that each structure has
    00234     //   not yet been set for this SetFeature() call.
    00235     */
    00236
    00237     pData = HidDevice -> FeatureData;
    00238
    00239     for (Index = 0; Index < HidDevice -> FeatureDataLength; Index++, pData++)
    00240     {
    00241         pData -> IsDataSet = FALSE;
    00242     }
    00243
    00244     /*
    00245     // In setting all the data in the reports, we need to pack a report buffer
    00246     //   and call WriteFile for each report ID that is represented by the
    00247     //   device structure.  To do so, the IsDataSet field will be used to
    00248     //   determine if a given report field has already been set.
    00249     */
    00250
    00251     Status = TRUE;
    00252
    00253     pData = HidDevice -> FeatureData;
    00254     for (Index = 0; Index < HidDevice -> FeatureDataLength; Index++, pData++)
    00255     {
    00256         if (!pData -> IsDataSet)
    00257         {
    00258             /*
    00259             // Package the report for this data structure.  PackReport will
    00260             //    set the IsDataSet fields of this structure and any other
    00261             //    structures that it includes in the report with this structure
    00262             */
    00263
    00264             PackReport (HidDevice->FeatureReportBuffer,
    00265                      HidDevice->Caps.FeatureReportByteLength,
    00266                      HidP_Feature,
    00267                      pData,
    00268                      HidDevice->FeatureDataLength - Index,
    00269                      HidDevice->Ppd);
    00270
    00271             /*
    00272             // Now a report has been packaged up...Send it down to the device
    00273             */
    00274
    00275             FeatureStatus =(HidD_SetFeature (HidDevice->HidDevice,
    00276                                           HidDevice->FeatureReportBuffer,
    00277                                           HidDevice->Caps.FeatureReportByteLength));
    00278
    00279             Status = Status && FeatureStatus;
    00280         }
    00281     }
    00282     return (Status);
    00283 }
    00284
    00285 BOOLEAN
    00286 GetFeature (
    00287    PHID_DEVICE    HidDevice
    00288 )
    00289 /*++
    00290 RoutineDescription:
    00291    Given a struct _HID_DEVICE, fill in the feature data structures with
    00292    all features on the device.  May issue multiple HidD_GetFeature() calls to
    00293    deal with multiple report IDs.
    00294 --*/
    00295 {
    00296     ULONG     Index;
    00297     PHID_DATA pData;
    00298     BOOLEAN   FeatureStatus;
    00299     BOOLEAN   Status;
    00300
    00301     /*
    00302     // As with writing data, the IsDataSet value in all the structures should be
    00303     //    set to FALSE to indicate that the value has yet to have been set
    00304     */
    00305
    00306     pData = HidDevice -> FeatureData;
    00307
    00308     for (Index = 0; Index < HidDevice -> FeatureDataLength; Index++, pData++)
    00309     {
    00310         pData -> IsDataSet = FALSE;
    00311     }
    00312
    00313     /*
    00314     // Next, each structure in the HID_DATA buffer is filled in with a value
    00315     //   that is retrieved from one or more calls to HidD_GetFeature.  The
    00316     //   number of calls is equal to the number of reportIDs on the device
    00317     */
    00318
    00319     Status = TRUE;
    00320     pData = HidDevice -> FeatureData;
    00321
    00322     for (Index = 0; Index < HidDevice -> FeatureDataLength; Index++, pData++)
    00323     {
    00324         /*
    00325         // If a value has yet to have been set for this structure, build a report
    00326         //    buffer with its report ID as the first byte of the buffer and pass
    00327         //    it in the HidD_GetFeature call.  Specifying the report ID in the
    00328         //    first specifies which report is actually retrieved from the device.
    00329         //    The rest of the buffer should be zeroed before the call
    00330         */
    00331
    00332         if (!pData -> IsDataSet)
    00333         {
    00334             memset(HidDevice -> FeatureReportBuffer, 0x00, HidDevice->Caps.FeatureReportByteLength);
    00335
    00336             HidDevice -> FeatureReportBuffer[0] = (UCHAR) pData -> ReportID;
    00337
    00338             FeatureStatus = HidD_GetFeature (HidDevice->HidDevice,
    00339                                               HidDevice->FeatureReportBuffer,
    00340                                               HidDevice->Caps.FeatureReportByteLength);
    00341
    00342             /*
    00343             // If the return value is TRUE, scan through the rest of the HID_DATA
    00344             //    structures and fill whatever values we can from this report
    00345             */
    00346
    00347
    00348             if (FeatureStatus)
    00349             {
    00350                 FeatureStatus = UnpackReport ( HidDevice->FeatureReportBuffer,
    00351                                            HidDevice->Caps.FeatureReportByteLength,
    00352                                            HidP_Feature,
    00353                                            HidDevice->FeatureData,
    00354                                            HidDevice->FeatureDataLength,
    00355                                            HidDevice->Ppd);
    00356             }
    00357
    00358             Status = Status && FeatureStatus;
    00359         }
    00360    }
    00361
    00362    return (Status);
    00363 }
    00364
    00365
    00366 BOOLEAN
    00367 UnpackReport (
    00368    IN       PCHAR                ReportBuffer,
    00369    IN       USHORT               ReportBufferLength,
    00370    IN       HIDP_REPORT_TYPE     ReportType,
    00371    IN OUT   PHID_DATA            Data,
    00372    IN       ULONG                DataLength,
    00373    IN       PHIDP_PREPARSED_DATA Ppd
    00374 )
    00375 /*++
    00376 Routine Description:
    00377    Given ReportBuffer representing a report from a HID device where the first
    00378    byte of the buffer is the report ID for the report, extract all the HID_DATA
    00379    in the Data list from the given report.
    00380 --*/
    00381 {
    00382     ULONG       numUsages; // Number of usages returned from GetUsages.
    00383     ULONG       i;
    00384     UCHAR       reportID;
    00385     ULONG       Index;
    00386     ULONG       nextUsage;
    00387
    00388     reportID = ReportBuffer[0];
    00389
    00390     for (i = 0; i < DataLength; i++, Data++)
    00391     {
    00392         if (reportID == Data->ReportID)
    00393         {
    00394             if (Data->IsButtonData)
    00395             {
    00396                 numUsages = Data->ButtonData.MaxUsageLength;
    00397
    00398                 Data->Status = HidP_GetUsages (ReportType,
    00399                                                Data->UsagePage,
    00400                                                0, // All collections
    00401                                                Data->ButtonData.Usages,
    00402                                                &numUsages,
    00403                                                Ppd,
    00404                                                ReportBuffer,
    00405                                                ReportBufferLength);
    00406
    00407
    00408                 //
    00409                 // Get usages writes the list of usages into the buffer
    00410                 // Data->ButtonData.Usages newUsage is set to the number of usages
    00411                 // written into this array.
    00412                 // A usage cannot not be defined as zero, so we'll mark a zero
    00413                 // following the list of usages to indicate the end of the list of
    00414                 // usages
    00415                 //
    00416                 // NOTE: One anomaly of the GetUsages function is the lack of ability
    00417                 //        to distinguish the data for one ButtonCaps from another
    00418                 //        if two different caps structures have the same UsagePage
    00419                 //        For instance:
    00420                 //          Caps1 has UsagePage 07 and UsageRange of 0x00 - 0x167
    00421                 //          Caps2 has UsagePage 07 and UsageRange of 0xe0 - 0xe7
    00422                 //
    00423                 //        However, calling GetUsages for each of the data structs
    00424                 //          will return the same list of usages.  It is the
    00425                 //          responsibility of the caller to set in the HID_DEVICE
    00426                 //          structure which usages actually are valid for the
    00427                 //          that structure.
    00428                 //
    00429
    00430                 /*
    00431                 // Search through the usage list and remove those that
    00432                 //    correspond to usages outside the define ranged for this
    00433                 //    data structure.
    00434                 */
    00435
    00436                 for (Index = 0, nextUsage = 0; Index < numUsages; Index++)
    00437                 {
    00438                     if (Data -> ButtonData.UsageMin <= Data -> ButtonData.Usages[Index] &&
    00439                             Data -> ButtonData.Usages[Index] <= Data -> ButtonData.UsageMax)
    00440                     {
    00441                         Data -> ButtonData.Usages[nextUsage++] = Data -> ButtonData.Usages[Index];
    00442
    00443                     }
    00444                 }
    00445
    00446                 if (nextUsage < Data -> ButtonData.MaxUsageLength)
    00447                 {
    00448                     Data->ButtonData.Usages[nextUsage] = 0;
    00449                 }
    00450             }
    00451             else
    00452             {
    00453                 Data->Status = HidP_GetUsageValue (
    00454                                                 ReportType,
    00455                                                 Data->UsagePage,
    00456                                                 0,               // All Collections.
    00457                                                 Data->ValueData.Usage,
    00458                                                 &Data->ValueData.Value,
    00459                                                 Ppd,
    00460                                                 ReportBuffer,
    00461                                                 ReportBufferLength);
    00462
    00463                 if (HIDP_STATUS_SUCCESS != Data->Status)
    00464                 {
    00465                     return (FALSE);
    00466                 }
    00467
    00468                 Data->Status = HidP_GetScaledUsageValue (
    00469                                                        ReportType,
    00470                                                        Data->UsagePage,
    00471                                                        0, // All Collections.
    00472                                                        Data->ValueData.Usage,
    00473                                                        &Data->ValueData.ScaledValue,
    00474                                                        Ppd,
    00475                                                        ReportBuffer,
    00476                                                        ReportBufferLength);
    00477             }
    00478             Data -> IsDataSet = TRUE;
    00479         }
    00480     }
    00481     return (TRUE);
    00482 }
    00483
    00484
    00485 BOOLEAN
    00486 PackReport (
    00487    OUT PCHAR                ReportBuffer,
    00488    IN  USHORT               ReportBufferLength,
    00489    IN  HIDP_REPORT_TYPE     ReportType,
    00490    IN  PHID_DATA            Data,
    00491    IN  ULONG                DataLength,
    00492    IN  PHIDP_PREPARSED_DATA Ppd
    00493    )
    00494 /*++
    00495 Routine Description:
    00496    This routine takes in a list of HID_DATA structures (DATA) and builds
    00497       in ReportBuffer the given report for all data values in the list that
    00498       correspond to the report ID of the first item in the list.
    00499
    00500    For every data structure in the list that has the same report ID as the first
    00501       item in the list will be set in the report.  Every data item that is
    00502       set will also have it's IsDataSet field marked with TRUE.
    00503
    00504    A return value of FALSE indicates an unexpected error occurred when setting
    00505       a given data value.  The caller should expect that assume that no values
    00506       within the given data structure were set.
    00507
    00508    A return value of TRUE indicates that all data values for the given report
    00509       ID were set without error.
    00510 --*/
    00511 {
    00512     ULONG       numUsages; // Number of usages to set for a given report.
    00513     ULONG       i;
    00514     ULONG       CurrReportID;
    00515
    00516     /*
    00517     // All report buffers that are initially sent need to be zero'd out
    00518     */
    00519
    00520     memset (ReportBuffer, (UCHAR) 0, ReportBufferLength);
    00521
    00522     /*
    00523     // Go through the data structures and set all the values that correspond to
    00524     //   the CurrReportID which is obtained from the first data structure
    00525     //   in the list
    00526     */
    00527
    00528     CurrReportID = Data -> ReportID;
    00529
    00530     for (i = 0; i < DataLength; i++, Data++)
    00531     {
    00532         /*
    00533         // There are two different ways to determine if we set the current data
    00534         //    structure:
    00535         //    1) Store the report ID were using and only attempt to set those
    00536         //        data structures that correspond to the given report ID.  This
    00537         //        example shows this implementation.
    00538         //
    00539         //    2) Attempt to set all of the data structures and look for the
    00540         //        returned status value of HIDP_STATUS_INVALID_REPORT_ID.  This
    00541         //        error code indicates that the given usage exists but has a
    00542         //        different report ID than the report ID in the current report
    00543         //        buffer
    00544         */
    00545
    00546         if (Data -> ReportID == CurrReportID)
    00547         {
    00548             if (Data->IsButtonData)
    00549             {
    00550                 numUsages = Data->ButtonData.MaxUsageLength;
    00551                 Data->Status = HidP_SetUsages (ReportType,
    00552                                                Data->UsagePage,
    00553                                                0, // All collections
    00554                                                Data->ButtonData.Usages,
    00555                                                &numUsages,
    00556                                                Ppd,
    00557                                                ReportBuffer,
    00558                                                ReportBufferLength);
    00559             }
    00560             else
    00561             {
    00562                 Data->Status = HidP_SetUsageValue (ReportType,
    00563                                                    Data->UsagePage,
    00564                                                    0, // All Collections.
    00565                                                    Data->ValueData.Usage,
    00566                                                    Data->ValueData.Value,
    00567                                                    Ppd,
    00568                                                    ReportBuffer,
    00569                                                    ReportBufferLength);
    00570             }
    00571
    00572             if (HIDP_STATUS_SUCCESS != Data->Status)
    00573             {
    00574                 return FALSE;
    00575             }
    00576         }
    00577     }
    00578
    00579     /*
    00580     // At this point, all data structures that have the same ReportID as the
    00581     //    first one will have been set in the given report.  Time to loop
    00582     //    through the structure again and mark all of those data structures as
    00583     //    having been set.
    00584     */
    00585
    00586     for (i = 0; i < DataLength; i++, Data++)
    00587     {
    00588         if (CurrReportID == Data -> ReportID)
    00589         {
    00590             Data -> IsDataSet = TRUE;
    00591         }
    00592     }
    00593     return (TRUE);
    00594 }
    00595

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines