SAMV71 Xplained Ultra Software Package 1.3

pnp.c

00001 /*++
00002 
00003 Copyright (c) 1996    Microsoft Corporation
00004 
00005 Module Name:
00006 
00007     pnp.c
00008 
00009 Abstract:
00010 
00011     This module contains the code
00012     for finding, adding, removing, and identifying hid devices.
00013 
00014 Environment:
00015 
00016     User mode
00017 
00018 --*/
00019 
00020 #include <basetyps.h>
00021 #include <stdlib.h>
00022 #include <wtypes.h>
00023 #include <setupapi.h>
00024 #include "hidsdi.h"
00025 #include "hid.h"
00026 #include <strsafe.h>
00027 
00028 BOOLEAN
00029 FindKnownHidDevices (
00030    OUT PHID_DEVICE * HidDevices, // A array of struct _HID_DEVICE
00031    OUT PULONG        NumberDevices // the length of this array.
00032    )
00033 /*++
00034 Routine Description:
00035    Do the required PnP things in order to find all the HID devices in
00036    the system at this time.
00037 --*/
00038 {
00039     HDEVINFO                            hardwareDeviceInfo;
00040     SP_DEVICE_INTERFACE_DATA            deviceInfoData;
00041     ULONG                               i;
00042     BOOLEAN                             done;
00043     PHID_DEVICE                         hidDeviceInst;
00044     GUID                                hidGuid;
00045     PSP_DEVICE_INTERFACE_DETAIL_DATA    functionClassDeviceData = NULL;
00046     ULONG                               predictedLength = 0;
00047     ULONG                               requiredLength = 0;
00048     PHID_DEVICE                         newHidDevices;
00049 
00050 
00051     HidD_GetHidGuid (&hidGuid);
00052 
00053     *HidDevices = NULL;
00054     *NumberDevices = 0;
00055 
00056     //
00057     // Open a handle to the plug and play dev node.
00058     //
00059     hardwareDeviceInfo = SetupDiGetClassDevs ( &hidGuid,
00060                                                NULL, // Define no enumerator (global)
00061                                                NULL, // Define no
00062                                                (DIGCF_PRESENT | // Only Devices present
00063                                                 DIGCF_DEVICEINTERFACE)); // Function class devices.
00064 
00065     //
00066     // Take a wild guess to start
00067     //
00068     
00069     *NumberDevices = 4;
00070     done = FALSE;
00071     deviceInfoData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
00072 
00073     i=0;
00074     while (!done) 
00075     {
00076         *NumberDevices *= 2;
00077 
00078         if (*HidDevices) 
00079         {
00080             newHidDevices =
00081                realloc (*HidDevices, (*NumberDevices * sizeof (HID_DEVICE)));
00082 
00083             if (NULL == newHidDevices)
00084             {
00085                 free(*HidDevices);                
00086             }
00087 
00088             *HidDevices = newHidDevices;
00089         }
00090         else
00091         {
00092             *HidDevices = calloc (*NumberDevices, sizeof (HID_DEVICE));
00093         }
00094 
00095         if (NULL == *HidDevices) 
00096         {
00097             SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
00098             return FALSE;
00099         }
00100 
00101         hidDeviceInst = *HidDevices + i;
00102 
00103         for (; i < *NumberDevices; i++, hidDeviceInst++) 
00104         {
00105             if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
00106                                              0, // No care about specific PDOs
00107                                              &hidGuid,
00108                                              i,
00109                                              &deviceInfoData))
00110             {
00111                 //
00112                 // allocate a function class device data structure to receive the
00113                 // goods about this particular device.
00114                 //
00115 
00116                 SetupDiGetDeviceInterfaceDetail (
00117                         hardwareDeviceInfo,
00118                         &deviceInfoData,
00119                         NULL, // probing so no output buffer yet
00120                         0, // probing so output buffer length of zero
00121                         &requiredLength,
00122                         NULL); // not interested in the specific dev-node
00123 
00124 
00125                 predictedLength = requiredLength;
00126 
00127                 functionClassDeviceData = malloc (predictedLength);
00128                 if (functionClassDeviceData)
00129                 {
00130                     functionClassDeviceData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
00131                 }
00132                 else
00133                 {
00134                     SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
00135                     return FALSE;
00136                 }
00137 
00138                 //
00139                 // Retrieve the information from Plug and Play.
00140                 //
00141 
00142                 if (! SetupDiGetDeviceInterfaceDetail (
00143                            hardwareDeviceInfo,
00144                            &deviceInfoData,
00145                            functionClassDeviceData,
00146                            predictedLength,
00147                            &requiredLength,
00148                            NULL)) 
00149                 {
00150                     SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
00151                     free(functionClassDeviceData);
00152                     return FALSE;
00153                 }
00154 
00155                 //
00156                 // Open device with just generic query abilities to begin with
00157                 //
00158                 
00159                 if (! OpenHidDevice (functionClassDeviceData -> DevicePath, 
00160                                FALSE,      // ReadAccess - none
00161                                FALSE,      // WriteAccess - none
00162                                FALSE,       // Overlapped - no
00163                                FALSE,       // Exclusive - no
00164                                hidDeviceInst))
00165                 {
00166                     SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
00167                     free(functionClassDeviceData);
00168                     return FALSE;
00169                 }
00170 
00171             } 
00172             else
00173             {
00174                 if (ERROR_NO_MORE_ITEMS == GetLastError()) 
00175                 {
00176                     done = TRUE;
00177                     break;
00178                 }
00179             }
00180         }
00181     }
00182 
00183     *NumberDevices = i;
00184 
00185     SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
00186     free(functionClassDeviceData);
00187     return TRUE;
00188 }
00189 
00190 BOOLEAN
00191 OpenHidDevice (
00192     IN       PCHAR          DevicePath,
00193     IN       BOOL           HasReadAccess,
00194     IN       BOOL           HasWriteAccess,
00195     IN       BOOL           IsOverlapped,
00196     IN       BOOL           IsExclusive,
00197     IN OUT   PHID_DEVICE    HidDevice
00198 )
00199 /*++
00200 RoutineDescription:
00201     Given the HardwareDeviceInfo, representing a handle to the plug and
00202     play information, and deviceInfoData, representing a specific hid device,
00203     open that device and fill in all the relivant information in the given
00204     HID_DEVICE structure.
00205 
00206     return if the open and initialization was successfull or not.
00207 
00208 --*/
00209 {
00210     DWORD   accessFlags = 0;
00211     DWORD   sharingFlags = 0;
00212     BOOLEAN bSuccess;
00213     INT     iDevicePathSize;
00214     HRESULT stringReturn;
00215 
00216     iDevicePathSize = strlen(DevicePath) + 1;
00217     
00218     HidDevice -> DevicePath = malloc(iDevicePathSize);
00219 
00220     if (NULL == HidDevice -> DevicePath) 
00221     {
00222         return (FALSE);
00223     }
00224 
00225     stringReturn = StringCbCopy(HidDevice -> DevicePath, iDevicePathSize, DevicePath);
00226     
00227     if (HasReadAccess)
00228     {
00229         accessFlags |= GENERIC_READ;
00230     }
00231 
00232     if (HasWriteAccess)
00233     {
00234         accessFlags |= GENERIC_WRITE;
00235     }
00236 
00237     if (!IsExclusive)
00238     {
00239         sharingFlags = FILE_SHARE_READ | FILE_SHARE_WRITE;
00240     }
00241     
00242     //
00243     //  The hid.dll api's do not pass the overlapped structure into deviceiocontrol
00244     //  so to use them we must have a non overlapped device.  If the request is for
00245     //  an overlapped device we will close the device below and get a handle to an
00246     //  overlapped device
00247     //
00248     
00249     HidDevice->HidDevice = CreateFile (DevicePath,
00250                                        accessFlags,
00251                                        sharingFlags,
00252                                        NULL,        // no SECURITY_ATTRIBUTES structure
00253                                        OPEN_EXISTING, // No special create flags
00254                                        0,   // Open device as non-overlapped so we can get data
00255                                        NULL);       // No template file
00256 
00257     if (INVALID_HANDLE_VALUE == HidDevice->HidDevice) 
00258     {
00259         free(HidDevice -> DevicePath);
00260         HidDevice -> DevicePath = INVALID_HANDLE_VALUE ;
00261         return FALSE;
00262     }
00263 
00264     HidDevice -> OpenedForRead = HasReadAccess;
00265     HidDevice -> OpenedForWrite = HasWriteAccess;
00266     HidDevice -> OpenedOverlapped = IsOverlapped;
00267     HidDevice -> OpenedExclusive = IsExclusive;
00268     
00269     //
00270     // If the device was not opened as overlapped, then fill in the rest of the
00271     //  HidDevice structure.  However, if opened as overlapped, this handle cannot
00272     //  be used in the calls to the HidD_ exported functions since each of these
00273     //  functions does synchronous I/O.
00274     //
00275 
00276     if (!HidD_GetPreparsedData (HidDevice->HidDevice, &HidDevice->Ppd)) 
00277     {
00278         free(HidDevice -> DevicePath);
00279         HidDevice -> DevicePath = NULL ;
00280         CloseHandle(HidDevice -> HidDevice);
00281         HidDevice -> HidDevice = INVALID_HANDLE_VALUE ;
00282         return FALSE;
00283     }
00284 
00285     if (!HidD_GetAttributes (HidDevice->HidDevice, &HidDevice->Attributes)) 
00286     {
00287         free(HidDevice -> DevicePath);
00288         HidDevice -> DevicePath = NULL;
00289         CloseHandle(HidDevice -> HidDevice);
00290         HidDevice -> HidDevice = INVALID_HANDLE_VALUE;
00291         HidD_FreePreparsedData (HidDevice->Ppd);
00292         HidDevice->Ppd = NULL;
00293 
00294         return FALSE;
00295     }
00296 
00297     if (!HidP_GetCaps (HidDevice->Ppd, &HidDevice->Caps))
00298     {
00299         free(HidDevice -> DevicePath);
00300         HidDevice -> DevicePath = NULL;
00301         CloseHandle(HidDevice -> HidDevice);
00302         HidDevice -> HidDevice = INVALID_HANDLE_VALUE;
00303         HidD_FreePreparsedData (HidDevice->Ppd);
00304         HidDevice->Ppd = NULL;
00305 
00306         return FALSE;
00307     }
00308 
00309     //
00310     // At this point the client has a choice.  It may chose to look at the
00311     // Usage and Page of the top level collection found in the HIDP_CAPS
00312     // structure.  In this way it could just use the usages it knows about.
00313     // If either HidP_GetUsages or HidP_GetUsageValue return an error then
00314     // that particular usage does not exist in the report.
00315     // This is most likely the preferred method as the application can only
00316     // use usages of which it already knows.
00317     // In this case the app need not even call GetButtonCaps or GetValueCaps.
00318     //
00319     // In this example, however, we will call FillDeviceInfo to look for all
00320     //    of the usages in the device.
00321     //
00322 
00323     bSuccess = FillDeviceInfo(HidDevice);
00324 
00325     if (FALSE == bSuccess)
00326     {
00327         CloseHidDevice(HidDevice);
00328         return (FALSE);
00329     }
00330     
00331     if (IsOverlapped)
00332     {
00333         CloseHandle(HidDevice->HidDevice);
00334 
00335         HidDevice->HidDevice = CreateFile (DevicePath,
00336                                        accessFlags,
00337                                        sharingFlags,
00338                                        NULL,        // no SECURITY_ATTRIBUTES structure
00339                                        OPEN_EXISTING, // No special create flags
00340                                        FILE_FLAG_OVERLAPPED, // Now we open the device as overlapped
00341                                        NULL);       // No template file
00342     
00343         if (INVALID_HANDLE_VALUE == HidDevice->HidDevice) 
00344         {
00345             CloseHidDevice(HidDevice);
00346             return FALSE;
00347         }
00348     }
00349 
00350     return (TRUE);
00351 }
00352 
00353 BOOLEAN
00354 FillDeviceInfo(
00355     IN  PHID_DEVICE HidDevice
00356 )
00357 {
00358     USHORT              numValues;
00359     USHORT              numCaps;
00360     PHIDP_BUTTON_CAPS   buttonCaps;
00361     PHIDP_VALUE_CAPS    valueCaps;
00362     PHID_DATA           data;
00363     ULONG               i;
00364     USAGE               usage;
00365 
00366     //
00367     // setup Input Data buffers.
00368     //
00369 
00370     //
00371     // Allocate memory to hold on input report
00372     //
00373 
00374     HidDevice->InputReportBuffer = (PCHAR) 
00375         calloc (HidDevice->Caps.InputReportByteLength, sizeof (CHAR));
00376 
00377 
00378     //
00379     // Allocate memory to hold the button and value capabilities.
00380     // NumberXXCaps is in terms of array elements.
00381     //
00382     
00383     HidDevice->InputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS)
00384         calloc (HidDevice->Caps.NumberInputButtonCaps, sizeof (HIDP_BUTTON_CAPS));
00385 
00386     if (NULL == buttonCaps)
00387     {
00388         return (FALSE);
00389     }
00390 
00391     HidDevice->InputValueCaps = valueCaps = (PHIDP_VALUE_CAPS)
00392         calloc (HidDevice->Caps.NumberInputValueCaps, sizeof (HIDP_VALUE_CAPS));
00393 
00394     if (NULL == valueCaps)
00395     {
00396         return(FALSE);
00397     }
00398 
00399     //
00400     // Have the HidP_X functions fill in the capability structure arrays.
00401     //
00402 
00403     numCaps = HidDevice->Caps.NumberInputButtonCaps;
00404 
00405     HidP_GetButtonCaps (HidP_Input,
00406                         buttonCaps,
00407                         &numCaps,
00408                         HidDevice->Ppd);
00409 
00410     numCaps = HidDevice->Caps.NumberInputValueCaps;
00411 
00412     HidP_GetValueCaps (HidP_Input,
00413                        valueCaps,
00414                        &numCaps,
00415                        HidDevice->Ppd);
00416 
00417 
00418     //
00419     // Depending on the device, some value caps structures may represent more
00420     // than one value.  (A range).  In the interest of being verbose, over
00421     // efficient, we will expand these so that we have one and only one
00422     // struct _HID_DATA for each value.
00423     //
00424     // To do this we need to count up the total number of values are listed
00425     // in the value caps structure.  For each element in the array we test
00426     // for range if it is a range then UsageMax and UsageMin describe the
00427     // usages for this range INCLUSIVE.
00428     //
00429     
00430     numValues = 0;
00431     for (i = 0; i < HidDevice->Caps.NumberInputValueCaps; i++, valueCaps++) 
00432     {
00433         if (valueCaps->IsRange) 
00434         {
00435             numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1;
00436         }
00437         else
00438         {
00439             numValues++;
00440         }
00441     }
00442     valueCaps = HidDevice->InputValueCaps;
00443 
00444 
00445     //
00446     // Allocate a buffer to hold the struct _HID_DATA structures.
00447     // One element for each set of buttons, and one element for each value
00448     // found.
00449     //
00450 
00451     HidDevice->InputDataLength = HidDevice->Caps.NumberInputButtonCaps
00452                                + numValues;
00453 
00454     HidDevice->InputData = data = (PHID_DATA)
00455         calloc (HidDevice->InputDataLength, sizeof (HID_DATA));
00456 
00457     if (NULL == data)
00458     {
00459         return (FALSE);
00460     }
00461 
00462     //
00463     // Fill in the button data
00464     //
00465 
00466     for (i = 0;
00467          i < HidDevice->Caps.NumberInputButtonCaps;
00468          i++, data++, buttonCaps++) 
00469     {
00470         data->IsButtonData = TRUE;
00471         data->Status = HIDP_STATUS_SUCCESS;
00472         data->UsagePage = buttonCaps->UsagePage;
00473         if (buttonCaps->IsRange) 
00474         {
00475             data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin;
00476             data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax;
00477         }
00478         else
00479         {
00480             data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage;
00481         }
00482         
00483         data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength (
00484                                                 HidP_Input,
00485                                                 buttonCaps->UsagePage,
00486                                                 HidDevice->Ppd);
00487         data->ButtonData.Usages = (PUSAGE)
00488             calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE));
00489 
00490         data->ReportID = buttonCaps -> ReportID;
00491     }
00492 
00493     //
00494     // Fill in the value data
00495     //
00496 
00497     for (i = 0; i < numValues; i++, valueCaps++)
00498     {
00499         if (valueCaps->IsRange) 
00500         {
00501             for (usage = valueCaps->Range.UsageMin;
00502                  usage <= valueCaps->Range.UsageMax;
00503                  usage++) 
00504             {
00505                 data->IsButtonData = FALSE;
00506                 data->Status = HIDP_STATUS_SUCCESS;
00507                 data->UsagePage = valueCaps->UsagePage;
00508                 data->ValueData.Usage = usage;
00509                 data->ReportID = valueCaps -> ReportID;
00510                 data++;
00511             }
00512         } 
00513         else
00514         {
00515             data->IsButtonData = FALSE;
00516             data->Status = HIDP_STATUS_SUCCESS;
00517             data->UsagePage = valueCaps->UsagePage;
00518             data->ValueData.Usage = valueCaps->NotRange.Usage;
00519             data->ReportID = valueCaps -> ReportID;
00520             data++;
00521         }
00522     }
00523 
00524     //
00525     // setup Output Data buffers.
00526     //
00527 
00528     HidDevice->OutputReportBuffer = (PCHAR)
00529         calloc (HidDevice->Caps.OutputReportByteLength, sizeof (CHAR));
00530 
00531     HidDevice->OutputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS)
00532         calloc (HidDevice->Caps.NumberOutputButtonCaps, sizeof (HIDP_BUTTON_CAPS));
00533 
00534     if (NULL == buttonCaps)
00535     {
00536         return (FALSE);
00537     }    
00538 
00539     HidDevice->OutputValueCaps = valueCaps = (PHIDP_VALUE_CAPS)
00540         calloc (HidDevice->Caps.NumberOutputValueCaps, sizeof (HIDP_VALUE_CAPS));
00541 
00542     if (NULL == valueCaps)
00543     {
00544         return (FALSE);
00545     }
00546 
00547     numCaps = HidDevice->Caps.NumberOutputButtonCaps;
00548     HidP_GetButtonCaps (HidP_Output,
00549                         buttonCaps,
00550                         &numCaps,
00551                         HidDevice->Ppd);
00552 
00553     numCaps = HidDevice->Caps.NumberOutputValueCaps;
00554     HidP_GetValueCaps (HidP_Output,
00555                        valueCaps,
00556                        &numCaps,
00557                        HidDevice->Ppd);
00558 
00559     numValues = 0;
00560     for (i = 0; i < HidDevice->Caps.NumberOutputValueCaps; i++, valueCaps++) 
00561     {
00562         if (valueCaps->IsRange) 
00563         {
00564             numValues += valueCaps->Range.UsageMax
00565                        - valueCaps->Range.UsageMin + 1;
00566         } 
00567         else
00568         {
00569             numValues++;
00570         }
00571     }
00572     valueCaps = HidDevice->OutputValueCaps;
00573 
00574     HidDevice->OutputDataLength = HidDevice->Caps.NumberOutputButtonCaps
00575                                 + numValues;
00576 
00577     HidDevice->OutputData = data = (PHID_DATA)
00578        calloc (HidDevice->OutputDataLength, sizeof (HID_DATA));
00579 
00580     if (NULL == data)
00581     {
00582         return (FALSE);
00583     }
00584 
00585     for (i = 0;
00586          i < HidDevice->Caps.NumberOutputButtonCaps;
00587          i++, data++, buttonCaps++) 
00588     {
00589         data->IsButtonData = TRUE;
00590         data->Status = HIDP_STATUS_SUCCESS;
00591         data->UsagePage = buttonCaps->UsagePage;
00592 
00593         if (buttonCaps->IsRange)
00594         {
00595             data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin;
00596             data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax;
00597         }
00598         else
00599         {
00600             data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage;
00601         }
00602 
00603         data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength (
00604                                                    HidP_Output,
00605                                                    buttonCaps->UsagePage,
00606                                                    HidDevice->Ppd);
00607 
00608         data->ButtonData.Usages = (PUSAGE)
00609             calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE));
00610 
00611         data->ReportID = buttonCaps -> ReportID;
00612     }
00613 
00614     for (i = 0; i < numValues; i++, valueCaps++)
00615     {
00616         if (valueCaps->IsRange)
00617         {
00618             for (usage = valueCaps->Range.UsageMin;
00619                  usage <= valueCaps->Range.UsageMax;
00620                  usage++) 
00621             {
00622                 data->IsButtonData = FALSE;
00623                 data->Status = HIDP_STATUS_SUCCESS;
00624                 data->UsagePage = valueCaps->UsagePage;
00625                 data->ValueData.Usage = usage;
00626                 data->ReportID = valueCaps -> ReportID;
00627                 data++;
00628             }
00629         }
00630         else
00631         {
00632             data->IsButtonData = FALSE;
00633             data->Status = HIDP_STATUS_SUCCESS;
00634             data->UsagePage = valueCaps->UsagePage;
00635             data->ValueData.Usage = valueCaps->NotRange.Usage;
00636             data->ReportID = valueCaps -> ReportID;
00637             data++;
00638         }
00639     }
00640 
00641     //
00642     // setup Feature Data buffers.
00643     //
00644 
00645     HidDevice->FeatureReportBuffer = (PCHAR)
00646            calloc (HidDevice->Caps.FeatureReportByteLength, sizeof (CHAR));
00647 
00648     HidDevice->FeatureButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS)
00649         calloc (HidDevice->Caps.NumberFeatureButtonCaps, sizeof (HIDP_BUTTON_CAPS));
00650 
00651     if (NULL == buttonCaps)
00652     {
00653         return (FALSE);
00654     }
00655 
00656     HidDevice->FeatureValueCaps = valueCaps = (PHIDP_VALUE_CAPS)
00657         calloc (HidDevice->Caps.NumberFeatureValueCaps, sizeof (HIDP_VALUE_CAPS));
00658 
00659     if (NULL == valueCaps)
00660     {
00661         return (FALSE);
00662     }
00663 
00664     numCaps = HidDevice->Caps.NumberFeatureButtonCaps;
00665     HidP_GetButtonCaps (HidP_Feature,
00666                         buttonCaps,
00667                         &numCaps,
00668                         HidDevice->Ppd);
00669 
00670     numCaps = HidDevice->Caps.NumberFeatureValueCaps;
00671     HidP_GetValueCaps (HidP_Feature,
00672                        valueCaps,
00673                        &numCaps,
00674                        HidDevice->Ppd);
00675 
00676     numValues = 0;
00677     for (i = 0; i < HidDevice->Caps.NumberFeatureValueCaps; i++, valueCaps++) 
00678     {
00679         if (valueCaps->IsRange) 
00680         {
00681             numValues += valueCaps->Range.UsageMax
00682                        - valueCaps->Range.UsageMin + 1;
00683         }
00684         else
00685         {
00686             numValues++;
00687         }
00688     }
00689     valueCaps = HidDevice->FeatureValueCaps;
00690 
00691     HidDevice->FeatureDataLength = HidDevice->Caps.NumberFeatureButtonCaps
00692                                  + numValues;
00693 
00694     HidDevice->FeatureData = data = (PHID_DATA)
00695         calloc (HidDevice->FeatureDataLength, sizeof (HID_DATA));
00696 
00697     if (NULL == data)
00698     {
00699         return (FALSE);
00700     }
00701 
00702 
00703     for (i = 0;
00704          i < HidDevice->Caps.NumberFeatureButtonCaps;
00705          i++, data++, buttonCaps++) 
00706     {
00707         data->IsButtonData = TRUE;
00708         data->Status = HIDP_STATUS_SUCCESS;
00709         data->UsagePage = buttonCaps->UsagePage;
00710 
00711         if (buttonCaps->IsRange)
00712         {
00713             data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin;
00714             data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax;
00715         }
00716         else
00717         {
00718             data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage;
00719         }
00720         
00721         data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength (
00722                                                 HidP_Feature,
00723                                                 buttonCaps->UsagePage,
00724                                                 HidDevice->Ppd);
00725         data->ButtonData.Usages = (PUSAGE)
00726              calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE));
00727 
00728         data->ReportID = buttonCaps -> ReportID;
00729     }
00730 
00731     for (i = 0; i < numValues; i++, valueCaps++) 
00732     {
00733         if (valueCaps->IsRange)
00734         {
00735             for (usage = valueCaps->Range.UsageMin;
00736                  usage <= valueCaps->Range.UsageMax;
00737                  usage++)
00738             {
00739                 data->IsButtonData = FALSE;
00740                 data->Status = HIDP_STATUS_SUCCESS;
00741                 data->UsagePage = valueCaps->UsagePage;
00742                 data->ValueData.Usage = usage;
00743                 data->ReportID = valueCaps -> ReportID;
00744                 data++;
00745             }
00746         } 
00747         else
00748         {
00749             data->IsButtonData = FALSE;
00750             data->Status = HIDP_STATUS_SUCCESS;
00751             data->UsagePage = valueCaps->UsagePage;
00752             data->ValueData.Usage = valueCaps->NotRange.Usage;
00753             data->ReportID = valueCaps -> ReportID;
00754             data++;
00755         }
00756     }
00757 
00758     return (TRUE);
00759 }
00760 
00761 VOID
00762 CloseHidDevices(
00763     IN  PHID_DEVICE HidDevices,
00764     IN  ULONG       NumberDevices
00765 )
00766 {
00767     ULONG   Index;
00768 
00769     for (Index = 0; Index < NumberDevices; Index++) 
00770     {
00771         CloseHidDevice(HidDevices+Index);
00772     }
00773 
00774     return;
00775 }
00776 
00777 VOID
00778 CloseHidDevice (
00779     IN PHID_DEVICE HidDevice
00780 )
00781 {
00782     free(HidDevice -> DevicePath);
00783     
00784     if (INVALID_HANDLE_VALUE != HidDevice -> HidDevice)
00785     {
00786         CloseHandle(HidDevice -> HidDevice);
00787         HidDevice -> HidDevice = INVALID_HANDLE_VALUE;
00788     }
00789     
00790     if (NULL != HidDevice -> Ppd)
00791     {
00792         HidD_FreePreparsedData(HidDevice -> Ppd);
00793         HidDevice -> Ppd = NULL;
00794     }
00795 
00796     if (NULL != HidDevice -> InputReportBuffer)
00797     {
00798         free(HidDevice -> InputReportBuffer);
00799         HidDevice -> InputReportBuffer = NULL;
00800     }
00801 
00802     if (NULL != HidDevice -> InputData)
00803     {
00804         free(HidDevice -> InputData);
00805         HidDevice -> InputData = NULL;
00806     }
00807 
00808     if (NULL != HidDevice -> InputButtonCaps)
00809     {
00810         free(HidDevice -> InputButtonCaps);
00811         HidDevice -> InputButtonCaps = NULL;
00812     }
00813 
00814     if (NULL != HidDevice -> InputValueCaps)
00815     {
00816         free(HidDevice -> InputValueCaps);
00817         HidDevice -> InputValueCaps = NULL;
00818     }
00819 
00820     if (NULL != HidDevice -> OutputReportBuffer)
00821     {
00822         free(HidDevice -> OutputReportBuffer);
00823         HidDevice -> OutputReportBuffer = NULL;
00824     }
00825 
00826     if (NULL != HidDevice -> OutputData)
00827     {
00828         free(HidDevice -> OutputData);
00829         HidDevice -> OutputData = NULL;
00830     }
00831 
00832     if (NULL != HidDevice -> OutputButtonCaps) 
00833     {
00834         free(HidDevice -> OutputButtonCaps);
00835         HidDevice -> OutputButtonCaps = NULL;
00836     }
00837 
00838     if (NULL != HidDevice -> OutputValueCaps)
00839     {
00840         free(HidDevice -> OutputValueCaps);
00841         HidDevice -> OutputValueCaps = NULL;
00842     }
00843 
00844     if (NULL != HidDevice -> FeatureReportBuffer)
00845     {
00846         free(HidDevice -> FeatureReportBuffer);
00847         HidDevice -> FeatureReportBuffer = NULL;
00848     }
00849 
00850     if (NULL != HidDevice -> FeatureData) 
00851     {
00852         free(HidDevice -> FeatureData);
00853         HidDevice -> FeatureData = NULL;
00854     }
00855 
00856     if (NULL != HidDevice -> FeatureButtonCaps) 
00857     {
00858         free(HidDevice -> FeatureButtonCaps);
00859         HidDevice -> FeatureButtonCaps = NULL;
00860     }
00861 
00862     if (NULL != HidDevice -> FeatureValueCaps) 
00863     {
00864         free(HidDevice -> FeatureValueCaps);
00865         HidDevice -> FeatureValueCaps = NULL;
00866     }
00867 
00868      return;
00869 }
00870 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines