He estado buscando lo que has puesto , te comento lo que tengo , supongo que ya lo abras visto aun asi , te lo paso.
Esto creo que es el codigo fuente del HID_ReadWrite, pero no lo tengo claro:
1. `//--------------------------------------------------------------------------
2. //
3. // USB HID Device and USB HID Device Manager Helper Classes
4. //
5. // The building blocks for this code was derived from the HCLIENT sample code
6. // provided by Microsoft in the Windows XP DDK.
7. //
8. //--------------------------------------------------------------------------
9. // $Archive: /WirelessUSB/LS2/Firmware/LP KBM RDK/Software/Source Code/CUSBHidAPI/HidAPI.cpp $
10. // $Modtime: 10/01/04 2:03p $
11. // $Revision: 2 $
12. //--------------------------------------------------------------------------
13. //
14. // Copyright 2003-2004, Cypress Semiconductor Corporation.
15. //
16. // This software is owned by Cypress Semiconductor Corporation (Cypress)
17. // and is protected by and subject to worldwide patent protection (United
18. // States and foreign), United States copyright laws and international
19. // treaty provisions. Cypress hereby grants to licensee a personal,
20. // non-exclusive, non-transferable license to copy, use, modify, create
21. // derivative works of, and compile the Cypress Source Code and derivative
22. // works for the sole purpose of creating custom software in support of
23. // licensee product to be used only in conjunction with a Cypress integrated
24. // circuit as specified in the applicable agreement. Any reproduction,
25. // modification, translation, compilation, or representation of this
26. // software except as specified above is prohibited without the express
27. // written permission of Cypress.
28. //
29. // Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
30. // WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32. // Cypress reserves the right to make changes without further notice to the
33. // materials described herein. Cypress does not assume any liability arising
34. // out of the application or use of any product or circuit described herein.
35. // Cypress does not authorize its products for use as critical components in
36. // life-support systems where a malfunction or failure may reasonably be
37. // expected to result in significant injury to the user. The inclusion of
38. // Cypress?product in a life-support systems application implies that the
39. // manufacturer assumes all risk of such use and in doing so indemnifies
40. // Cypress against all charges.
41. //
42. // Use may be limited by and subject to the applicable Cypress software
43. // license agreement.
44. //
45. //--------------------------------------------------------------------------
46. #include "StdAfx.h"
47. #include <dbt.h>
48.
49. #include "hidapi.h"
50.
51.
52. #define HIDMANAGER_CLASS _T("CHidManager")
53. CHidManager* CHidManager::m_pThis = NULL;
54. OSVERSIONINFO m_OS;
55.
56. bool CHidDevice::InitializeHidDevice(PCHAR pDevicePath, USHORT uID)
57. {
58. nextHidDevice = NULL;
59.
60. m_bOpened = false;
61.
62. m_hDevice = NULL;
63. m_hDeviceRegistered = NULL;
64. m_hWnd = NULL;
65.
66. m_bOpenedForRead = false;
67. m_bOpenedForWrite = false;
68. m_bOpenedOverlapped = false;
69. m_bOpenedExclusive = false;
70.
71. m_uDeviceID = uID;
72.
73. m_pHidDevicePath = NULL;
74. m_pHidPpd = NULL;
75. ::ZeroMemory(&m_HidCaps, sizeof(m_HidCaps));
76. ::ZeroMemory(&m_HidAttributes, sizeof(m_HidAttributes));
77.
78. m_pInputReportBuffer = NULL;
79. m_pInputData = NULL;
80. m_ulInputDataLength = 0;
81. m_pInputButtonCaps = NULL;
82. m_pInputValueCaps = NULL;
83.
84. m_pOutputReportBuffer = NULL;
85. m_pOutputData = NULL;
86. m_ulOutputDataLength = 0;
87. m_pOutputButtonCaps = NULL;
88. m_pOutputValueCaps = NULL;
89.
90. m_pFeatureReportBuffer = NULL;
91. m_pFeatureData = NULL;
92. m_ulFeatureDataLength = 0;
93. m_pFeatureButtonCaps = NULL;
94. m_pFeatureValueCaps = NULL;
95.
96. m_pHidDevicePath = new CHAR[lstrlen(pDevicePath)+1];
97. if (!m_pHidDevicePath)
98. return false;
99.
100. ::strcpy(m_pHidDevicePath, pDevicePath);
101.
102. return true;
103. }
104.
105. void CHidDevice::DestroyHidDevice()
106. {
107. if (m_bOpened)
108. {
109. CloseHidDevice();
110. }
111.
112. if (m_pHidDevicePath)
113. delete [] m_pHidDevicePath;
114.
115. m_uDeviceID = 0xFFFF;
116. }
117.
118. // sets appropriate access rights, attempts to open a
119. // handle to the HID device, obtains the top collection data, and
120. // makes a call to setup input, output, and feature data buffers.
121. bool CHidDevice::OpenHidDevice( bool bReadAccess,
122. bool bWriteAccess,
123. bool bUseOverlapped,
124. bool bExclusive)
125. {
126. DWORD accessFlags = 0;
127. DWORD sharingFlags = 0;
128.
129. // Check for valid device path
130. if (!m_pHidDevicePath)
131. {
132. return false;
133. }
134.
135. // setup access flag values
136. if (bReadAccess)
137. {
138. accessFlags |= GENERIC_READ;
139. }
140.
141. if (bWriteAccess)
142. {
143. accessFlags |= GENERIC_WRITE;
144. }
145.
146. if (!bExclusive)
147. {
148. sharingFlags = FILE_SHARE_READ | FILE_SHARE_WRITE;
149. }
150.
151. //
152. // The hid.dll api's do not pass the overlapped structure into deviceiocontrol
153. // so to use them we must have a non overlapped device. If the request is for
154. // an overlapped device we will close the device below and get a handle to an
155. // overlapped device
156. //
157.
158. m_hDevice = ::CreateFile (m_pHidDevicePath,
159. accessFlags,
160. sharingFlags,
161. NULL, // no SECURITY_ATTRIBUTES structure
162. OPEN_EXISTING, // No special create flags
163. 0, // Open device as non-overlapped so we can get data
164. NULL); // No template file
165.
166. if (m_hDevice == INVALID_HANDLE_VALUE)
167. {
168. return false;
169. }
170.
171. // open was successful
172. m_bOpened = true;
173.
174. // set access booleans appropriately
175. m_bOpenedForRead = bReadAccess;
176. m_bOpenedForWrite = bWriteAccess;
177. m_bOpenedOverlapped = bUseOverlapped;
178. m_bOpenedExclusive = bExclusive;
179.
180. // obtain the top level collection's preparsed data from the HID device.
181. // the top level collection is a HID collection that is not nested with
182. // other collections. a HID collection is a meaningful group of HID controls
183. // and their respective HID usages.
184. if (!::HidD_GetPreparsedData (m_hDevice, &m_pHidPpd))
185. {
186. // if failure, close HID handle and return failure
187. CloseHidDevice();
188. return false;
189. }
190.
191. // get the attributes of the top level collection
192. if (!::HidD_GetAttributes (m_hDevice, &m_HidAttributes))
193. {
194. // if failure, close HID handle, free preparsed data
195. // and return failure
196. ::HidD_FreePreparsedData (m_pHidPpd);
197. m_pHidPpd = NULL;
198.
199. CloseHidDevice();
200. return false;
201. }
202.
203. // get the top level collections capability
204. if (!::HidP_GetCaps (m_pHidPpd, &m_HidCaps))
205. {
206. // if failure, close HID handle, free preparsed data
207. // and return failure
208. ::HidD_FreePreparsedData (m_pHidPpd);
209. m_pHidPpd = NULL;
210.
211. CloseHidDevice();
212. return false;
213. }
214.
215. // attempt to setup the HID device
216. if (!SetupHidDevice())
217. {
218. // if failure, close HID handle, free preparsed data
219. // and return failure
220. ::HidD_FreePreparsedData (m_pHidPpd);
221. m_pHidPpd = NULL;
222.
223. CloseHidDevice();
224. return false;
225. }
226.
227. //
228. // At this point the client has a choice. It may chose to look at the
229. // Usage and Page of the top level collection found in the HIDP_CAPS
230. // structure. In this way it could just use the usages it knows about.
231. // If either HidP_GetUsages or HidP_GetUsageValue return an error then
232. // that particular usage does not exist in the report.
233. //
234.
235. // verify that this is a HID device we care about
236. if (!VerifyHidDevice())
237. {
238. // if failure, close HID handle, free preparsed data
239. // and return failure
240. ::HidD_FreePreparsedData (m_pHidPpd);
241. m_pHidPpd = NULL;
242.
243. CloseHidDevice();
244. return false;
245. }
246.
247. // if overlapped I/O requested, close handle and reopen using overlapped I/O
248. if (bUseOverlapped)
249. {
250. ::CloseHandle(m_hDevice);
251.
252. m_hDevice = ::CreateFile (m_pHidDevicePath,
253. accessFlags,
254. sharingFlags,
255. NULL, // no SECURITY_ATTRIBUTES structure
256. OPEN_EXISTING, // No special create flags
257. FILE_FLAG_OVERLAPPED, // Now we open the device as overlapped
258. NULL); // No template file
259.
260. if (m_hDevice == INVALID_HANDLE_VALUE)
261. {
262. // if failure, close HID handle, free preparsed data
263. // and return failure
264. ::HidD_FreePreparsedData (m_pHidPpd);
265. m_pHidPpd = NULL;
266.
267. CloseHidDevice();
268. return false;
269. }
270. }
271.
272. return true;
273. }
274.
275. // registers the HID device handle for event notification, mainly to get
276. // notified when the device is removed
277. bool CHidDevice::RegisterHidDevice(HWND hWnd)
278. {
279. DEV_BROADCAST_HANDLE broadcastHandle;
280.
281. broadcastHandle.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
282. broadcastHandle.dbch_devicetype = DBT_DEVTYP_HANDLE;
283. broadcastHandle.dbch_handle = m_hDevice;
284.
285. m_hDeviceRegistered = ::RegisterDeviceNotification(hWnd, (PVOID) &broadcastHandle, DEVICE_NOTIFY_WINDOW_HANDLE);
286. if (!m_hDeviceRegistered)
287. return false;
288.
289. m_hWnd = hWnd;
290.
291. return true;
292. }
293.
294. // sets up HID input, output and feature data buffers
295. // used to simplify communication with HID devices
296. bool CHidDevice::SetupHidDevice()
297. {
298. USHORT numCaps;
299. ULONG i;
300. USAGE usage;
301.
302. PHIDP_VALUE_CAPS valueCaps;
303. PHIDP_BUTTON_CAPS buttonCaps;
304. PHID_DATA data;
305. USHORT numValues;
306.
307. //
308. // setup Input Data buffers.
309. //
310.
311. //
312. // Allocate memory to hold on input report
313. //
314.
315. if (m_HidCaps.InputReportByteLength)
316. {
317. m_pInputReportBuffer = new CHAR[m_HidCaps.InputReportByteLength];
318. if (m_pInputReportBuffer)
319. ZeroMemory (m_pInputReportBuffer, m_HidCaps.InputReportByteLength);
320. }
321.
322. //
323. // Allocate memory to hold the button and value capabilities.
324. // NumberXXCaps is in terms of array elements.
325. //
326.
327. if (m_HidCaps.NumberInputButtonCaps)
328. {
329. m_pInputButtonCaps = new HIDP_BUTTON_CAPS[m_HidCaps.NumberInputButtonCaps];
330. if (!m_pInputButtonCaps)
331. return false;
332.
333. ZeroMemory (m_pInputButtonCaps, m_HidCaps.NumberInputButtonCaps * sizeof(HIDP_BUTTON_CAPS));
334.
335. numCaps = m_HidCaps.NumberInputButtonCaps;
336. ::HidP_GetButtonCaps (HidP_Input,
337. m_pInputButtonCaps,
338. &numCaps,
339. m_pHidPpd);
340. }
341.
342. if (m_HidCaps.NumberInputValueCaps)
343. {
344. m_pInputValueCaps = new HIDP_VALUE_CAPS[m_HidCaps.NumberInputValueCaps];
345. if (!m_pInputValueCaps)
346. return false;
347.
348. ZeroMemory (m_pInputValueCaps, m_HidCaps.NumberInputValueCaps * sizeof(HIDP_VALUE_CAPS));
349.
350. numCaps = m_HidCaps.NumberInputValueCaps;
351. ::HidP_GetValueCaps (HidP_Input,
352. m_pInputValueCaps,
353. &numCaps,
354. m_pHidPpd);
355. }
356.
357. //
358. // Depending on the device, some value caps structures may represent more
359. // than one value. (A range). In the interest of being verbose, over
360. // efficient, we will expand these so that we have one and only one
361. // struct _HID_DATA for each value.
362. //
363. // To do this we need to count up the total number of values are listed
364. // in the value caps structure. For each element in the array we test
365. // for range if it is a range then UsageMax and UsageMin describe the
366. // usages for this range INCLUSIVE.
367. //
368.
369. valueCaps = m_pInputValueCaps;
370. numValues = 0;
371.
372. if (valueCaps)
373. {
374. for (i = 0; i < m_HidCaps.NumberInputValueCaps; i++, valueCaps++)
375. {
376. if (valueCaps->IsRange)
377. {
378. numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1;
379. }
380. else
381. {
382. numValues++;
383. }
384. }
385. }
386.
387. //
388. // Allocate a buffer to hold the struct _HID_DATA structures.
389. // One element for each set of buttons, and one element for each value
390. // found.
391. //
392.
393. m_ulInputDataLength = m_HidCaps.NumberInputButtonCaps + numValues;
394.
395. if (m_ulInputDataLength)
396. {
397. m_pInputData = new HID_DATA[m_ulInputDataLength];
398. if (!m_pInputData)
399. return false;
400.
401. ZeroMemory (m_pInputData, m_ulInputDataLength * sizeof(HID_DATA));
402. }
403.
404. //
405. // Fill in the button data
406. //
407.
408. buttonCaps = m_pInputButtonCaps;
409. data = m_pInputData;
410.
411. if (buttonCaps && data)
412. {
413. for (i = 0;
414. i < m_HidCaps.NumberInputButtonCaps;
415. i++, data++, buttonCaps++)
416. {
417. data->IsButtonData = true;
418. data->Status = HIDP_STATUS_SUCCESS;
419. data->UsagePage = buttonCaps->UsagePage;
420. if (buttonCaps->IsRange)
421. {
422. data->ButtonData.UsageMin = buttonCaps->Range.UsageMin;
423. data->ButtonData.UsageMax = buttonCaps->Range.UsageMax;
424. }
425. else
426. {
427. data->ButtonData.UsageMin = data->ButtonData.UsageMax = buttonCaps->NotRange.Usage;
428. }
429.
430. data->ButtonData.MaxUsageLength = ::HidP_MaxUsageListLength (
431. HidP_Input,
432. buttonCaps->UsagePage,
433. m_pHidPpd);
434.
435. data->ButtonData.Usages = new USAGE[data->ButtonData.MaxUsageLength];
436. ZeroMemory (data->ButtonData.Usages, data->ButtonData.MaxUsageLength * sizeof(USAGE));
437.
438. data->ReportID = buttonCaps->ReportID;
439. }
440. }
441.
442. //
443. // Fill in the value data
444. //
445.
446. valueCaps = m_pInputValueCaps;
447.
448. if (valueCaps)
449. {
450. for (i = 0; i < numValues; i++, valueCaps++)
451. {
452. if (valueCaps->IsRange)
453. {
454. for (usage = valueCaps->Range.UsageMin;
455. usage <= valueCaps->Range.UsageMax;
456. usage++)
457. {
458. data->IsButtonData = false;
459. data->Status = HIDP_STATUS_SUCCESS;
460. data->UsagePage = valueCaps->UsagePage;
461. data->ValueData.Usage = usage;
462. data->ReportID = valueCaps->ReportID;
463. data++;
464. }
465. }
466. else
467. {
468. data->IsButtonData = false;
469. data->Status = HIDP_STATUS_SUCCESS;
470. data->UsagePage = valueCaps->UsagePage;
471. data->ValueData.Usage = valueCaps->NotRange.Usage;
472. data->ReportID = valueCaps->ReportID;
473. data++;
474. }
475. }
476. }
477.
478. //
479. // setup Output Data buffers.
480. //
481.
482. if (m_HidCaps.OutputReportByteLength)
483. {
484. m_pOutputReportBuffer = new CHAR[m_HidCaps.OutputReportByteLength];
485. if (m_pOutputReportBuffer)
486. ZeroMemory (m_pOutputReportBuffer, m_HidCaps.OutputReportByteLength);
487. }
488.
489. if (m_HidCaps.NumberOutputButtonCaps)
490. {
491. m_pOutputButtonCaps = new HIDP_BUTTON_CAPS[m_HidCaps.NumberOutputButtonCaps];
492. if (!m_pOutputButtonCaps)
493. return false;
494.
495. ZeroMemory (m_pOutputButtonCaps, m_HidCaps.NumberOutputButtonCaps * sizeof(HIDP_BUTTON_CAPS));
496.
497. numCaps = m_HidCaps.NumberOutputButtonCaps;
498. ::HidP_GetButtonCaps (HidP_Output,
499. m_pOutputButtonCaps,
500. &numCaps,
501. m_pHidPpd);
502. }
503.
504. if (m_HidCaps.NumberOutputValueCaps)
505. {
506. m_pOutputValueCaps = new HIDP_VALUE_CAPS[m_HidCaps.NumberOutputValueCaps];
507. if (!m_pOutputValueCaps)
508. return false;
509.
510. ZeroMemory (m_pOutputValueCaps, m_HidCaps.NumberOutputValueCaps * sizeof(HIDP_VALUE_CAPS));
511.
512. numCaps = m_HidCaps.NumberOutputValueCaps;
513. ::HidP_GetValueCaps (HidP_Output,
514. m_pOutputValueCaps,
515. &numCaps,
516. m_pHidPpd);
517. }
518.
519. valueCaps = m_pOutputValueCaps;
520. numValues = 0;
521.
522. if (valueCaps)
523. {
524. for (i = 0; i < m_HidCaps.NumberOutputValueCaps; i++, valueCaps++)
525. {
526. if (valueCaps->IsRange)
527. {
528. numValues += valueCaps->Range.UsageMax
529. - valueCaps->Range.UsageMin + 1;
530. }
531. else
532. {
533. numValues++;
534. }
535. }
536. }
537.
538. m_ulOutputDataLength = m_HidCaps.NumberOutputButtonCaps + numValues;
539.
540. if (m_ulOutputDataLength)
541. {
542. m_pOutputData = new HID_DATA[m_ulOutputDataLength];
543. if (!m_pOutputData)
544. return false;
545.
546. ZeroMemory (m_pOutputData, m_ulOutputDataLength * sizeof(HID_DATA));
547. }
548.
549. buttonCaps = m_pOutputButtonCaps;
550. data = m_pOutputData;
551.
552. if (buttonCaps && data)
553. {
554. for (i = 0;
555. i < m_HidCaps.NumberOutputButtonCaps;
556. i++, data++, buttonCaps++)
557. {
558. data->IsButtonData = true;
559. data->Status = HIDP_STATUS_SUCCESS;
560. data->UsagePage = buttonCaps->UsagePage;
561.
562. if (buttonCaps->IsRange)
563. {
564. data->ButtonData.UsageMin = buttonCaps->Range.UsageMin;
565. data->ButtonData.UsageMax = buttonCaps->Range.UsageMax;
566. }
567. else
568. {
569. data->ButtonData.UsageMin = data->ButtonData.UsageMax = buttonCaps->NotRange.Usage;
570. }
571.
572. data->ButtonData.MaxUsageLength = ::HidP_MaxUsageListLength (
573. HidP_Output,
574. buttonCaps->UsagePage,
575. m_pHidPpd);
576.
577. data->ButtonData.Usages = new USAGE[data->ButtonData.MaxUsageLength];
578. ZeroMemory (data->ButtonData.Usages, data->ButtonData.MaxUsageLength * sizeof(USAGE));
579.
580. data->ReportID = buttonCaps->ReportID;
581. }
582. }
583.
584. valueCaps = m_pOutputValueCaps;
585.
586. if (valueCaps)
587. {
588. for (i = 0; i < numValues; i++, valueCaps++)
589. {
590. if (valueCaps->IsRange)
591. {
592. for (usage = valueCaps->Range.UsageMin;
593. usage <= valueCaps->Range.UsageMax;
594. usage++)
595. {
596. data->IsButtonData = false;
597. data->Status = HIDP_STATUS_SUCCESS;
598. data->UsagePage = valueCaps->UsagePage;
599. data->ValueData.Usage = usage;
600. data->ReportID = valueCaps->ReportID;
601. data++;
602. }
603. }
604. else
605. {
606. data->IsButtonData = false;
607. data->Status = HIDP_STATUS_SUCCESS;
608. data->UsagePage = valueCaps->UsagePage;
609. data->ValueData.Usage = valueCaps->NotRange.Usage;
610. data->ReportID = valueCaps->ReportID;
611. data++;
612. }
613. }
614. }
615.
616. //
617. // setup Feature Data buffers.
618. //
619.
620. if (m_HidCaps.FeatureReportByteLength)
621. {
622. m_pFeatureReportBuffer = new CHAR[m_HidCaps.FeatureReportByteLength];
623. if (m_pFeatureReportBuffer)
624. ZeroMemory (m_pFeatureReportBuffer, m_HidCaps.FeatureReportByteLength);
625. }
626.
627. if (m_HidCaps.NumberFeatureButtonCaps)
628. {
629. m_pFeatureButtonCaps = new HIDP_BUTTON_CAPS[m_HidCaps.NumberFeatureButtonCaps];
630. if (!m_pFeatureButtonCaps)
631. return false;
632.
633. ZeroMemory (m_pFeatureButtonCaps, m_HidCaps.NumberFeatureButtonCaps * sizeof(HIDP_BUTTON_CAPS));
634.
635. numCaps = m_HidCaps.NumberFeatureButtonCaps;
636. ::HidP_GetButtonCaps (HidP_Feature,
637. m_pFeatureButtonCaps,
638. &numCaps,
639. m_pHidPpd);
640. }
641.
642. if (m_HidCaps.NumberFeatureValueCaps)
643. {
644. m_pFeatureValueCaps = new HIDP_VALUE_CAPS[m_HidCaps.NumberFeatureValueCaps];
645. if (!m_pFeatureValueCaps)
646. return false;
647.
648. ZeroMemory (m_pFeatureValueCaps, m_HidCaps.NumberFeatureValueCaps * sizeof(HIDP_VALUE_CAPS));
649.
650. numCaps = m_HidCaps.NumberFeatureValueCaps;
651. ::HidP_GetValueCaps (HidP_Feature,
652. m_pFeatureValueCaps,
653. &numCaps,
654. m_pHidPpd);
655. }
656.
657. valueCaps = m_pFeatureValueCaps;
658. numValues = 0;
659.
660. if (valueCaps)
661. {
662. for (i = 0; i < m_HidCaps.NumberFeatureValueCaps; i++, valueCaps++)
663. {
664. if (valueCaps->IsRange)
665. {
666. numValues += valueCaps->Range.UsageMax
667. - valueCaps->Range.UsageMin + 1;
668. }
669. else
670. {
671. numValues++;
672. }
673. }
674. }
675.
676. m_ulFeatureDataLength = m_HidCaps.NumberFeatureButtonCaps + numValues;
677.
678. if (m_ulFeatureDataLength)
679. {
680. m_pFeatureData = new HID_DATA[m_ulFeatureDataLength];
681. if (!m_pFeatureData)
682. return false;
683.
684. ZeroMemory (m_pFeatureData, m_ulFeatureDataLength * sizeof(HID_DATA));
685. }
686.
687. buttonCaps = m_pFeatureButtonCaps;
688. data = m_pFeatureData;
689.
690. if (buttonCaps && data)
691. {
692. for (i = 0;
693. i < m_HidCaps.NumberFeatureButtonCaps;
694. i++, data++, buttonCaps++)
695. {
696. data->IsButtonData = true;
697. data->Status = HIDP_STATUS_SUCCESS;
698. data->UsagePage = buttonCaps->UsagePage;
699.
700. if (buttonCaps->IsRange)
701. {
702. data->ButtonData.UsageMin = buttonCaps->Range.UsageMin;
703. data->ButtonData.UsageMax = buttonCaps->Range.UsageMax;
704. }
705. else
706. {
707. data->ButtonData.UsageMin = data->ButtonData.UsageMax = buttonCaps->NotRange.Usage;
708. }
709.
710. data->ButtonData.MaxUsageLength = ::HidP_MaxUsageListLength (
711. HidP_Feature,
712. buttonCaps->UsagePage,
713. m_pHidPpd);
714.
715. data->ButtonData.Usages = new USAGE[data->ButtonData.MaxUsageLength];
716. ZeroMemory (data->ButtonData.Usages, data->ButtonData.MaxUsageLength * sizeof(USAGE));
717.
718. data->ReportID = buttonCaps->ReportID;
719. }
720. }
721.
722. valueCaps = m_pFeatureValueCaps;
723.
724. if (valueCaps)
725. {
726. for (i = 0; i < numValues; i++, valueCaps++)
727. {
728. if (valueCaps->IsRange)
729. {
730. for (usage = valueCaps->Range.UsageMin;
731. usage <= valueCaps->Range.UsageMax;
732. usage++)
733. {
734. data->IsButtonData = false;
735. data->Status = HIDP_STATUS_SUCCESS;
736. data->UsagePage = valueCaps->UsagePage;
737. data->ValueData.Usage = usage;
738. data->ReportID = valueCaps->ReportID;
739. data++;
740. }
741. }
742. else
743. {
744. data->IsButtonData = false;
745. data->Status = HIDP_STATUS_SUCCESS;
746. data->UsagePage = valueCaps->UsagePage;
747. data->ValueData.Usage = valueCaps->NotRange.Usage;
748. data->ReportID = valueCaps->ReportID;
749. data++;
750. }
751. }
752. }
753.
754. return true;
755. }
756.
757. // closes HID device handle, unregisters HID device notification,
758. // frees prepased data and data/report buffers
759. bool CHidDevice::CloseHidDevice()
760. {
761. // close handle, if valid
762. if (m_hDevice != INVALID_HANDLE_VALUE)
763. {
764. ::CloseHandle(m_hDevice);
765. m_hDevice = INVALID_HANDLE_VALUE;
766. }
767.
768. // if HID device is registered, then unregister
769. if (m_hDeviceRegistered)
770. {
771. PostMessage(m_hWnd, WM_UNREGISTER_HANDLE, 0, (LPARAM) m_hDeviceRegistered);
772. m_hDeviceRegistered = NULL;
773. m_hWnd = NULL;
774. }
775.
776. // free preparsed data
777. if (m_pHidPpd)
778. {
779. ::HidD_FreePreparsedData(m_pHidPpd);
780. m_pHidPpd = NULL;
781. }
782.
783. // free input report buffer
784. if (m_pInputReportBuffer)
785. {
786. delete [] m_pInputReportBuffer;
787. m_pInputReportBuffer = NULL;
788. }
789.
790. // free input data buffer
791. if (m_pInputData)
792. {
793. PHID_DATA data = m_pInputData;
794.
795. if (data->ButtonData.Usages)
796. {
797. delete [] data->ButtonData.Usages;
798. }
799.
800. delete [] m_pInputData;
801. m_pInputData = NULL;
802. }
803.
804. // free input button caps
805. if (m_pInputButtonCaps)
806. {
807. delete [] m_pInputButtonCaps;
808. m_pInputButtonCaps = NULL;
809. }
810.
811. // free input value caps
812. if (m_pInputValueCaps)
813. {
814. delete [] m_pInputValueCaps;
815. m_pInputValueCaps = NULL;
816. }
817.
818. // free output report buffer
819. if (m_pOutputReportBuffer)
820. {
821. delete [] m_pOutputReportBuffer;
822. m_pOutputReportBuffer = NULL;
823. }
824.
825. // free output data buffer
826. if (m_pOutputData)
827. {
828. PHID_DATA data = m_pOutputData;
829.
830. if (data->ButtonData.Usages)
831. {
832. delete [] data->ButtonData.Usages;
833. }
834.
835. delete [] m_pOutputData;
836. m_pOutputData = NULL;
837. }
838.
839. // free output button caps
840. if (m_pOutputButtonCaps)
841. {
842. delete [] m_pOutputButtonCaps;
843. m_pOutputButtonCaps = NULL;
844. }
845.
846. // free output value caps
847. if (m_pOutputValueCaps)
848. {
849. delete [] m_pOutputValueCaps;
850. m_pOutputValueCaps = NULL;
851. }
852.
853. // free feature report buffer
854. if (m_pFeatureReportBuffer)
855. {
856. delete [] m_pFeatureReportBuffer;
857. m_pFeatureReportBuffer = NULL;
858. }
859.
860. // free feature data buffer
861. if (m_pFeatureData)
862. {
863. PHID_DATA data = m_pFeatureData;
864.
865. if (data->ButtonData.Usages)
866. {
867. delete [] data->ButtonData.Usages;
868. }
869.
870. delete [] m_pFeatureData;
871. m_pFeatureData = NULL;
872. }
873.
874. // free feature button caps
875. if (m_pFeatureButtonCaps)
876. {
877. delete [] m_pFeatureButtonCaps;
878. m_pFeatureButtonCaps = NULL;
879. }
880.
881. // free feature values caps
882. if (m_pFeatureValueCaps)
883. {
884. delete [] m_pFeatureValueCaps;
885. m_pFeatureValueCaps = NULL;
886. }
887.
888. // set open to false
889. m_bOpened = false;
890.
891. return true;
892. }
893.
894. // reads an input report from the HID device, performs
895. // a validity check, and unpacks the report data
896. bool CHidDevice::Read()
897. {
898. DWORD bytesRead;
899.
900. // read the input report data
901. if (!ReadFile (m_hDevice,
902. m_pInputReportBuffer,
903. m_HidCaps.InputReportByteLength,
904. &bytesRead,
905. NULL)) // no overlapped
906. {
907. return false;
908. }
909.
910. // make sure it was valid, ensure bytes read is what
911. // is expected for this report
912. ASSERT (bytesRead == m_HidCaps.InputReportByteLength);
913. if (bytesRead != m_HidCaps.InputReportByteLength)
914. {
915. return false;
916. }
917.
918. // unpack the report data into a more useful form
919. return UnpackReport (HidP_Input,
920. m_pInputReportBuffer,
921. m_HidCaps.InputReportByteLength,
922. m_pInputData,
923. m_ulInputDataLength,
924. m_pHidPpd);
925. }
926.
927. // for every report ID, pack a report buffer and write the report data to the HID device
928. bool CHidDevice::Write()
929. {
930. DWORD bytesWritten;
931. PHID_DATA pData;
932. ULONG Index;
933. bool Status;
934. bool WriteStatus;
935.
936. // Begin by looping through the HID_DEVICE's HID_DATA structure and setting
937. // the IsDataSet field to false to indicate that each structure has
938. // not yet been set for this Write call.
939.
940. pData = m_pOutputData;
941. if (!pData)
942. return false;
943.
944. for (Index = 0; Index < m_ulOutputDataLength; Index++, pData++)
945. {
946. pData->IsDataSet = false;
947. }
948.
949. // In setting all the data in the reports, we need to pack a report buffer
950. // and call WriteFile for each report ID that is represented by the
951. // device structure. To do so, the IsDataSet field will be used to
952. // determine if a given report field has already been set.
953.
954. Status = true;
955.
956. pData = m_pOutputData;
957. if (!pData)
958. return false;
959.
960. for (Index = 0; Index < m_ulOutputDataLength; Index++, pData++)
961. {
962. if (!pData->IsDataSet)
963. {
964. // Package the report for this data structure. PackReport will
965. // set the IsDataSet fields of this structure and any other
966. // structures that it includes in the report with this structure
967.
968. PackReport (HidP_Output,
969. m_pOutputReportBuffer,
970. m_HidCaps.OutputReportByteLength,
971. pData,
972. m_ulOutputDataLength - Index,
973. m_pHidPpd);
974.
975. // Now a report has been packaged up...Send it down to the device
976.
977. WriteStatus = WriteFile (m_hDevice,
978. m_pOutputReportBuffer,
979. m_HidCaps.OutputReportByteLength,
980. &bytesWritten,
981. NULL) && (bytesWritten == m_HidCaps.OutputReportByteLength);
982.
983. Status = Status && WriteStatus;
984. }
985. }
986.
987. return Status;
988. }
989.
990. // obtains the feature report from each report ID exposed by the HID device
991. bool CHidDevice::GetFeature()
992. {
993. ULONG Index;
994. PHID_DATA pData;
995. BOOLEAN bReportStatus;
996. bool bStatus;
997.
998. // Begin by looping through the HID_DEVICE's HID_DATA structure and setting
999. // the IsDataSet field to false to indicate that each structure has
1000. // not yet been set for this SetFeature() call.
1001.
1002. pData = m_pFeatureData;
1003. if (!pData)
1004. return false;
1005.
1006. for (Index = 0; Index < m_ulFeatureDataLength; Index++, pData++)
1007. {
1008. pData->IsDataSet = false;
1009. }
1010.
1011. // Next, each structure in the HID_DATA buffer is filled in with a value
1012. // that is retrieved from one or more calls to HidD_GetFeature. The
1013. // number of calls is equal to the number of reportIDs on the device
1014.
1015. bStatus = true;
1016.
1017. pData = m_pFeatureData;
1018. if (!pData)
1019. return false;
1020.
1021. for (Index = 0; Index < m_ulFeatureDataLength; Index++, pData++)
1022. {
1023. // If a value has yet to have been set for this structure, build a report
1024. // buffer with its report ID as the first byte of the buffer and pass
1025. // it in the HidD_GetFeature call. Specifying the report ID in the
1026. // first specifies which report is actually retrieved from the device.
1027. // The rest of the buffer should be zeroed before the call
1028.
1029. if (!pData->IsDataSet)
1030. {
1031. memset(m_pFeatureReportBuffer, 0x00, m_HidCaps.FeatureReportByteLength);
1032.
1033. m_pFeatureReportBuffer[0] = (UCHAR) pData->ReportID;
1034.
1035. bReportStatus = HidD_GetFeature (m_hDevice,
1036. m_pFeatureReportBuffer,
1037. m_HidCaps.FeatureReportByteLength);
1038.
1039. // If the return value is true, scan through the rest of the HID_DATA
1040. // structures and fill whatever values we can from this report
1041.
1042. if (bReportStatus)
1043. {
1044. bReportStatus = UnpackReport (HidP_Feature,
1045. m_pFeatureReportBuffer,
1046. m_HidCaps.FeatureReportByteLength,
1047. m_pFeatureData,
1048. m_ulFeatureDataLength,
1049. m_pHidPpd);
1050. }
1051.
1052. bStatus = bStatus && bReportStatus;
1053. }
1054. }
1055.
1056. return bStatus;
1057. }
1058.
1059. // send a feature report for each report ID exposed by the HID device
1060. bool CHidDevice::SetFeature()
1061. {
1062. PHID_DATA pData;
1063. ULONG Index;
1064. BOOLEAN bReportStatus;
1065. bool bStatus;
1066.
1067. // Begin by looping through the HID_DEVICE's HID_DATA structure and setting
1068. // the IsDataSet field to false to indicate that each structure has
1069. // not yet been set for this SetFeature() call.
1070.
1071. pData = m_pFeatureData;
1072. if (!pData)
1073. return false;
1074.
1075. for (Index = 0; Index < m_ulFeatureDataLength; Index++, pData++)
1076. {
1077. pData->IsDataSet = false;
1078. }
1079.
1080. // In setting all the data in the reports, we need to pack a report buffer
1081. // and call WriteFile for each report ID that is represented by the
1082. // device structure. To do so, the IsDataSet field will be used to
1083. // determine if a given report field has already been set.
1084.
1085. bStatus = true;
1086.
1087. pData = m_pFeatureData;
1088. if (!pData)
1089. return false;
1090.
1091. for (Index = 0; Index < m_ulFeatureDataLength; Index++, pData++)
1092. {
1093. if (!pData->IsDataSet)
1094. {
1095. // Package the report for this data structure. PackReport will
1096. // set the IsDataSet fields of this structure and any other
1097. // structures that it includes in the report with this structure
1098.
1099. PackReport (HidP_Feature,
1100. m_pFeatureReportBuffer,
1101. m_HidCaps.FeatureReportByteLength,
1102. m_pFeatureData,
1103. m_ulFeatureDataLength - Index,
1104. m_pHidPpd);
1105.
1106. bReportStatus =(HidD_SetFeature (m_hDevice,
1107. m_pFeatureReportBuffer,
1108. m_HidCaps.FeatureReportByteLength));
1109.
1110. bStatus = bStatus && bReportStatus;
1111. }
1112. }
1113.
1114. return bStatus;
1115. }
1116.
1117. // scans though the HID data report and fills in any values it can
1118. bool CHidDevice::UnpackReport(
1119. HIDP_REPORT_TYPE ReportType,
1120. PCHAR ReportBuffer,
1121. USHORT ReportBufferLength,
1122. PHID_DATA Data,
1123. ULONG DataLength,
1124. PHIDP_PREPARSED_DATA Ppd
1125. )
1126. {
1127. ULONG numUsages; // Number of usages returned from GetUsages.
1128. ULONG i;
1129. UCHAR reportID;
1130. ULONG Index;
1131. ULONG nextUsage;
1132.
1133. reportID = ReportBuffer[0];
1134.
1135. for (i = 0; i < DataLength; i++, Data++)
1136. {
1137. if (reportID == Data->ReportID)
1138. {
1139. if (Data->IsButtonData)
1140. {
1141. numUsages = Data->ButtonData.MaxUsageLength;
1142.
1143. Data->Status = HidP_GetUsages (ReportType,
1144. Data->UsagePage,
1145. 0, // All collections
1146. Data->ButtonData.Usages,
1147. &numUsages,
1148. Ppd,
1149. ReportBuffer,
1150. ReportBufferLength);
1151.
1152.
1153. // Get usages writes the list of usages into the buffer
1154. // Data->ButtonData.Usages newUsage is set to the number of usages
1155. // written into this array.
1156. // A usage cannot not be defined as zero, so we'll mark a zero
1157. // following the list of usages to indicate the end of the list of
1158. // usages
1159. //
1160. // NOTE: One anomaly of the GetUsages function is the lack of ability
1161. // to distinguish the data for one ButtonCaps from another
1162. // if two different caps structures have the same UsagePage
1163. // For instance:
1164. // Caps1 has UsagePage 07 and UsageRange of 0x00 - 0x167
1165. // Caps2 has UsagePage 07 and UsageRange of 0xe0 - 0xe7
1166. //
1167. // However, calling GetUsages for each of the data structs
1168. // will return the same list of usages. It is the
1169. // responsibility of the caller to set in the HID_DEVICE
1170. // structure which usages actually are valid for the
1171. // that structure.
1172. //
1173.
1174. // Search through the usage list and remove those that
1175. // correspond to usages outside the define ranged for this
1176. // data structure.
1177.
1178. for (Index = 0, nextUsage = 0; Index < numUsages; Index++)
1179. {
1180. if (Data->ButtonData.UsageMin <= Data->ButtonData.Usages[Index] &&
1181. Data->ButtonData.Usages[Index] <= Data->ButtonData.UsageMax)
1182. {
1183. Data->ButtonData.Usages[nextUsage++] = Data->ButtonData.Usages[Index];
1184. }
1185. }
1186.
1187. if (nextUsage < Data->ButtonData.MaxUsageLength)
1188. {
1189. Data->ButtonData.Usages[nextUsage] = 0;
1190. }
1191. }
1192. else
1193. {
1194. Data->Status = HidP_GetUsageValue (
1195. ReportType,
1196. Data->UsagePage,
1197. 0, // All Collections.
1198. Data->ValueData.Usage,
1199. &Data->ValueData.Value,
1200. Ppd,
1201. ReportBuffer,
1202. ReportBufferLength);
1203.
1204. if (HIDP_STATUS_SUCCESS != Data->Status)
1205. {
1206. return false;
1207. }
1208.
1209. Data->Status = HidP_GetScaledUsageValue (
1210. ReportType,
1211. Data->UsagePage,
1212. 0, // All Collections.
1213. Data->ValueData.Usage,
1214. &Data->ValueData.ScaledValue,
1215. Ppd,
1216. ReportBuffer,
1217. ReportBufferLength);
1218. }
1219.
1220. Data->IsDataSet = true;
1221. }
1222. }
1223.
1224. return true;
1225. }
1226.
1227. // packages the HID report based on the data in the structures
1228. bool CHidDevice::PackReport(
1229. HIDP_REPORT_TYPE ReportType,
1230. PCHAR ReportBuffer,
1231. USHORT ReportBufferLength,
1232. PHID_DATA Data,
1233. ULONG DataLength,
1234. PHIDP_PREPARSED_DATA Ppd
1235. )
1236. {
1237. ULONG numUsages; // Number of usages to set for a given report.
1238. ULONG i;
1239. ULONG CurrReportID;
1240.
1241. // All report buffers that are initially sent need to be zero'd out
1242.
1243. memset (ReportBuffer, (UCHAR) 0, ReportBufferLength);
1244.
1245. // Go through the data structures and set all the values that correspond to
1246. // the CurrReportID which is obtained from the first data structure
1247. // in the list
1248.
1249. CurrReportID = Data->ReportID;
1250.
1251. for (i = 0; i < DataLength; i++, Data++)
1252. {
1253. // There are two different ways to determine if we set the current data
1254. // structure:
1255. // 1) Store the report ID were using and only attempt to set those
1256. // data structures that correspond to the given report ID. This
1257. // example shows this implementation.
1258. //
1259. // 2) Attempt to set all of the data structures and look for the
1260. // returned status value of HIDP_STATUS_INVALID_REPORT_ID. This
1261. // error code indicates that the given usage exists but has a
1262. // different report ID than the report ID in the current report
1263. // buffer
1264.
1265. if (Data->ReportID == CurrReportID)
1266. {
1267. if (Data->IsButtonData)
1268. {
1269. numUsages = Data->ButtonData.MaxUsageLength;
1270. Data->Status = HidP_SetUsages (ReportType,
1271. Data->UsagePage,
1272. 0, // All collections
1273. Data->ButtonData.Usages,
1274. &numUsages,
1275. Ppd,
1276. ReportBuffer,
1277. ReportBufferLength);
1278. }
1279. else
1280. {
1281. Data->Status = HidP_SetUsageValue (ReportType,
1282. Data->UsagePage,
1283. 0, // All Collections.
1284. Data->ValueData.Usage,
1285. Data->ValueData.Value,
1286. Ppd,
1287. ReportBuffer,
1288. ReportBufferLength);
1289. }
1290.
1291. if (HIDP_STATUS_SUCCESS != Data->Status)
1292. {
1293. return false;
1294. }
1295.
1296. Data->IsDataSet = true;
1297. }
1298. }
1299.
1300. return true;
1301. }
1302.
1303. // obtains the manufacturer string from the HID device
1304. bool CHidDevice::GetManufacturerString(PCHAR szManufacturerString, ULONG ulManufacturerStringLength)
1305. {
1306. PWCHAR str = new WCHAR[ulManufacturerStringLength];
1307.
1308. if (str)
1309. {
1310. // attempt to get the manufacturer string, which is in Unicode format
1311. BOOLEAN result = HidD_GetManufacturerString(m_hDevice, str, ulManufacturerStringLength*sizeof(WCHAR));
1312.
1313. if (result)
1314. {
1315. // converts the wide character string (Unicode) to multi-byte string
1316. SIZE_T nBytes = wcstombs(szManufacturerString, str, ulManufacturerStringLength-1);
1317. if ((SIZE_T) -1 != nBytes)
1318. {
1319. delete str;
1320. return true;
1321. }
1322. }
1323.
1324. delete str;
1325. }
1326.
1327. return false;
1328. }
1329.
1330. // obtains the product string from the HID device
1331. bool CHidDevice::GetProductString(PCHAR szProductString, ULONG ulProductStringLength)
1332. {
1333. PWCHAR str = new WCHAR[ulProductStringLength];
1334.
1335. if (str)
1336. {
1337. // attempt to get the product string, which is in Unicode format
1338. BOOLEAN result = HidD_GetProductString(m_hDevice, str, ulProductStringLength*sizeof(WCHAR));
1339.
1340. if (result)
1341. {
1342. // converts the wide character string (Unicode) to multi-byte string
1343. SIZE_T nBytes = wcstombs(szProductString, str, ulProductStringLength-1);
1344. if ((SIZE_T) -1 != nBytes)
1345. {
1346. delete str;
1347. return true;
1348. }
1349. }
1350.
1351. delete str;
1352. }
1353.
1354. return false;
1355. }
1356.
1357. // obtains the serial numbert string from the HID device
1358. bool CHidDevice::GetSerialNumberString(PCHAR szSerialNumberString, ULONG ulSerialNumberStringLength)
1359. {
1360. PWCHAR str = new WCHAR[ulSerialNumberStringLength];
1361.
1362. if (str)
1363. {
1364. // attempt to get the serial number string, which is in Unicode format
1365. BOOLEAN result = HidD_GetSerialNumberString(m_hDevice, str, ulSerialNumberStringLength*sizeof(WCHAR));
1366.
1367. if (result)
1368. {
1369. // converts the wide character string (Unicode) to multi-byte string
1370. SIZE_T nBytes = wcstombs(szSerialNumberString, str, ulSerialNumberStringLength-1);
1371. if ((SIZE_T) -1 != nBytes)
1372. {
1373. delete str;
1374. return true;
1375. }
1376. }
1377.
1378. delete str;
1379. }
1380.
1381. return false;
1382. }
1383.
1384. // attempts to get a registry value from the registry key where the
1385. // device-specific configuration information is stored for the HID device
1386. bool CHidDevice::RegQueryValue(LPCTSTR lpValueName,
1387. LPDWORD lpType,
1388. LPBYTE lpData,
1389. LPDWORD lpcbData)
1390. {
1391. bool ret = false;
1392.
1393. HDEVINFO hwDeviceInfo;
1394. SP_DEVICE_INTERFACE_DATA devInterfaceData;
1395. GUID hidGuid;
1396.
1397.
1398. // get a copy of the HID GUID to be used below
1399. HidD_GetHidGuid (&hidGuid);
1400.
1401. // get a list of all HID devices present in the system
1402. hwDeviceInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
1403. if (hwDeviceInfo != INVALID_HANDLE_VALUE)
1404. {
1405. HKEY hkEnum;
1406.
1407. // loop through all HID devices, looking for a match for this specific HID device
1408. int iEnumInfo = 0;
1409. devInterfaceData.cbSize = sizeof(devInterfaceData);
1410. while ( SetupDiEnumDeviceInterfaces(hwDeviceInfo, 0, (CONST LPGUID)&hidGuid, iEnumInfo++, &devInterfaceData) )
1411. {
1412. SP_DEVINFO_DATA devInfoData;
1413. PSP_INTERFACE_DEVICE_DETAIL_DATA functionClassDeviceData;
1414. ULONG requiredLength = 0;
1415. ULONG predictedLength = 0;
1416.
1417. SetupDiGetInterfaceDeviceDetail (
1418. hwDeviceInfo,
1419. &devInterfaceData,
1420. NULL,
1421. 0,
1422. &requiredLength,
1423. NULL);
1424.
1425. predictedLength = requiredLength;
1426.
1427. // allocate the device data
1428. devInfoData.cbSize = sizeof(devInfoData);
1429. functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) new UCHAR[predictedLength];
1430. functionClassDeviceData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA);
1431.
1432. // retrieve the information from Plug and Play
1433. if (SetupDiGetInterfaceDeviceDetail(hwDeviceInfo, &devInterfaceData, functionClassDeviceData, predictedLength, &requiredLength, &devInfoData))
1434. {
1435. // check to see if this HID device is a match
1436. if (strcmpi(functionClassDeviceData->DevicePath, m_pHidDevicePath) == 0)
1437. {
1438. // found a match, open a handle to the registry
1439. // where device-specific configuration information
1440. // is stored
1441. hkEnum = SetupDiOpenDevRegKey ( hwDeviceInfo,
1442. &devInfoData,
1443. DICS_FLAG_GLOBAL,
1444. 0,
1445. DIREG_DEV,
1446. KEY_ALL_ACCESS );
1447.
1448. if (hkEnum != INVALID_HANDLE_VALUE)
1449. {
1450. // if the reg handle was open, attempt to obtain
1451. // the registry value
1452. if (RegQueryValueEx(hkEnum,
1453. lpValueName,
1454. NULL,
1455. lpType,
1456. lpData,
1457. lpcbData
1458. ) == ERROR_SUCCESS)
1459. {
1460. // indicate success
1461. ret = true;
1462. }
1463.
1464. // close the reg handle
1465. RegCloseKey ( hkEnum );
1466. }
1467.
1468. // release the allocated device data and
1469. // leave the loop
1470. delete [] functionClassDeviceData;
1471. break;
1472. }
1473. }
1474.
1475. // release the allocated device data
1476. delete [] functionClassDeviceData;
1477. }
1478.
1479. // destroy the list that was created above
1480. SetupDiDestroyDeviceInfoList(hwDeviceInfo);
1481. }
1482.
1483. return ret;
1484. }
1485.
1486. // attempts to set a registry value in the registry key where the
1487. // device-specific configuration information is stored for the HID device
1488. bool CHidDevice::RegSetValue(LPCTSTR lpValueName,
1489. DWORD Type,
1490. LPBYTE lpData,
1491. DWORD cbData)
1492. {
1493. bool ret = false;
1494.
1495. HDEVINFO hwDeviceInfo;
1496. SP_DEVICE_INTERFACE_DATA devInterfaceData;
1497. GUID hidGuid;
1498.
1499.
1500. // get a copy of the HID GUID to be used below
1501. HidD_GetHidGuid (&hidGuid);
1502.
1503. // get a list of all HID devices present in the system
1504. hwDeviceInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
1505. if (hwDeviceInfo != INVALID_HANDLE_VALUE)
1506. {
1507. HKEY hkEnum;
1508.
1509. // loop through all HID devices, looking for a match for this specific HID device
1510. int iEnumInfo = 0;
1511. devInterfaceData.cbSize = sizeof(devInterfaceData);
1512. while ( SetupDiEnumDeviceInterfaces(hwDeviceInfo, 0, (CONST LPGUID)&hidGuid, iEnumInfo++, &devInterfaceData) )
1513. {
1514. SP_DEVINFO_DATA devInfoData;
1515. PSP_INTERFACE_DEVICE_DETAIL_DATA functionClassDeviceData;
1516. ULONG requiredLength = 0;
1517. ULONG predictedLength = 0;
1518.
1519. SetupDiGetInterfaceDeviceDetail (
1520. hwDeviceInfo,
1521. &devInterfaceData,
1522. NULL,
1523. 0,
1524. &requiredLength,
1525. NULL);
1526.
1527. predictedLength = requiredLength;
1528.
1529. // allocate the device data
1530. devInfoData.cbSize = sizeof(devInfoData);
1531. functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) new UCHAR[predictedLength];
1532. functionClassDeviceData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA);
1533.
1534. // retrieve the information from Plug and Play
1535. if (SetupDiGetInterfaceDeviceDetail(hwDeviceInfo, &devInterfaceData, functionClassDeviceData, predictedLength, &requiredLength, &devInfoData))
1536. {
1537. // check to see if this HID device is a match
1538. if (strcmpi(functionClassDeviceData->DevicePath, m_pHidDevicePath) == 0)
1539. {
1540. // found a match, open a handle to the registry
1541. // where device-specific configuration information
1542. // is stored
1543. hkEnum = SetupDiOpenDevRegKey ( hwDeviceInfo,
1544. &devInfoData,
1545. DICS_FLAG_GLOBAL,
1546. 0,
1547. DIREG_DEV,
1548. KEY_ALL_ACCESS );
1549.
1550. if (hkEnum != INVALID_HANDLE_VALUE)
1551. {
1552. if (RegSetValueEx(hkEnum,
1553. lpValueName,
1554. NULL,
1555. Type,
1556. lpData,
1557. cbData
1558. ) == ERROR_SUCCESS)
1559. {
1560. // indicate success
1561. ret = true;
1562. }
1563.
1564. // close the reg handle
1565. RegCloseKey ( hkEnum );
1566. }
1567.
1568. // release the allocated device data and
1569. // leave the loop
1570. delete [] functionClassDeviceData;
1571. break;
1572. }
1573. }
1574.
1575. // release the allocated device data
1576. delete [] functionClassDeviceData;
1577. }
1578.
1579. // destroy the list that was created above
1580. SetupDiDestroyDeviceInfoList(hwDeviceInfo);
1581. }
1582.
1583. return ret;
1584. }
1585.
1586.
1587. CHidManager::CHidManager()
1588. {
1589. m_OS.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1590. GetVersionEx( &m_OS );
1591.
1592. InitializeHidManager();
1593. }
1594.
1595. CHidManager::~CHidManager(void)
1596. {
1597. // remove all HID devices in the maintained list
1598. RemoveAllHidDevices();
1599.
1600. // destroy the invisible window, if it exists
1601. if (m_hWnd)
1602. {
1603. ::DestroyWindow(m_hWnd);
1604. m_hWnd = NULL;
1605. }
1606.
1607. // if we registered for notificiation for this device, then clean up
1608. if (m_hDeviceNotification)
1609. {
1610. // issue callback indicating the device notification is being unregistered
1611. if (m_pHidCallback) (*m_pHidCallback)(m_pHidCallbackParam, NULL, HIDCB_NOTIFY_DEVICE_UNREGISTERED);
1612.
1613. // unregister device notification
1614. // NOTE: for Windows 98x, it can become unstable if you unregister the device notification
1615. if (m_OS.dwMajorVersion > 4)
1616. {
1617. ::UnregisterDeviceNotification(m_hDeviceNotification);
1618. }
1619. m_hDeviceNotification = NULL;
1620. }
1621.
1622. // NULL callback function and parameter pointers
1623. m_pHidCallback = NULL;
1624. m_pHidCallbackParam = NULL;
1625. }
1626.
1627. // standard initialization
1628. void CHidManager::InitializeHidManager()
1629. {
1630. m_pThis = this;
1631.
1632. m_bEnabled = false;
1633. m_hWnd = NULL;
1634. m_hDeviceNotification = NULL;
1635. m_pHidCallback = NULL;
1636. m_pHidCallbackParam = NULL;
1637.
1638. m_pHidDeviceListHead = NULL;
1639. m_pCurrentHidDevice = NULL;
1640. m_nHidDevices = 0;
1641.
1642. ZeroMemory(m_bUniqueIDs, HIDMGR_SUPPORTED_HID_DEVICES);
1643. }
1644.
1645.
1646. // registers for notification of events for all HID class devices and
1647. // calls HID callback function to indicate registration was completed
1648. bool CHidManager::RegisterHidNotification(HWND hWnd)
1649. {
1650. DEV_BROADCAST_DEVICEINTERFACE broadcastInterface = {0};
1651.
1652. broadcastInterface.dbcc_size = sizeof(broadcastInterface);
1653. broadcastInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
1654.
1655. // get HID GUID
1656. ::HidD_GetHidGuid(&broadcastInterface.dbcc_classguid);
1657.
1658. m_hDeviceNotification = ::RegisterDeviceNotification(hWnd, (PVOID) &broadcastInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
1659. if (!m_hDeviceNotification) return false;
1660.
1661. if (m_pHidCallback) (*m_pHidCallback)(m_pHidCallbackParam, NULL, HIDCB_NOTIFY_DEVICE_REGISTERED);
1662.
1663. return true;
1664. }
1665.
1666.
1667. // registers a window class for subsequent use in calls to CreateWindow, used below
1668. ATOM CHidManager::RegisterClass(HINSTANCE hInstance)
1669. {
1670. WNDCLASSEX wcex;
1671.
1672. wcex.cbSize = sizeof(WNDCLASSEX);
1673.
1674. wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
1675. //wcex.lpfnWndProc = (WNDPROC)WindowProc; /////////////////////////////////////////////
1676. wcex.cbClsExtra = 0;
1677. wcex.cbWndExtra = 0;
1678. wcex.hInstance = hInstance;
1679. wcex.hIcon = 0;
1680. wcex.hCursor = 0;
1681. wcex.hbrBackground = 0;
1682. wcex.lpszMenuName = 0;
1683. wcex.lpszClassName = HIDMANAGER_CLASS;
1684. wcex.hIconSm = 0;
1685.
1686. return ::RegisterClassEx(&wcex);
1687. }
1688.
1689. // creates an invisible window and uses the returned window handle
1690. // to register for HID device notification events, then it creates
1691. // a list of existing HID devices that will be maintained by the
1692. // HID manager
1693. bool CHidManager::Create(HINSTANCE hInst, HWND hParentWnd, PHidCallback pHidCallback, void *pHidCallbackParam)
1694. {
1695. bool bResult = true;
1696.
1697. m_pHidCallback = pHidCallback;
1698. m_pHidCallbackParam = pHidCallbackParam;
1699.
1700. // class so WindowProc function is called
1701. RegisterClass(hInst);
1702.
1703. // Create an invisible window
1704. m_hWnd = ::CreateWindow(HIDMANAGER_CLASS, _T(""), WS_POPUP,
1705. CW_USEDEFAULT,CW_USEDEFAULT,
1706. CW_USEDEFAULT,CW_USEDEFAULT,
1707. NULL, 0,
1708. hInst, 0);
1709.
1710. if (!RegisterHidNotification(m_hWnd))
1711. {
1712. bResult = false;
1713. }
1714.
1715. if (bResult)
1716. {
1717. // setup all existing and valid HID devices
1718. RefreshHidDevices();
1719.
1720. // everything was created successfully
1721. m_bEnabled = true;
1722. }
1723.
1724. return bResult;
1725. }
1726.
1727. // attempts to open a handle to the HID device to determine
1728. // if it is present (or not) and returns the result
1729. bool CHidManager::IsHidDevicePresent(CHidDevice *pHidDevice)
1730. {
1731. // attempt to open a handle to the HID device, if the device
1732. // is present then this should return success
1733. HANDLE h = ::CreateFile(pHidDevice->m_pHidDevicePath,
1734. GENERIC_WRITE | GENERIC_READ,
1735. FILE_SHARE_WRITE | FILE_SHARE_READ,
1736. NULL,
1737. OPEN_EXISTING,
1738. 0,
1739. NULL);
1740.
1741. if (h != INVALID_HANDLE_VALUE)
1742. {
1743. // close handle and indicate device is present
1744. ::CloseHandle(h);
1745. return true;
1746. }
1747.
1748. return false;
1749. }
1750.
1751. // attempts to create and maintain a unique ID for the associated HID device
1752. USHORT CHidManager::CreateUniqueDeviceID()
1753. {
1754. USHORT i;
1755.
1756. for (i=0;i<hidmgr_supported_hid_devices;i++) (!m_buniqueids[i])="" m_buniqueids[i]="true;" i;="" return="" 0xffff;="" }="" frees="" the="" specified="" unique="" id="" void="" chidmanager::freeuniquedeviceid(ushort="" uid)="" {="" if="" (uid="">< HIDMGR_SUPPORTED_HID_DEVICES)
1757. {
1758. m_bUniqueIDs[uID] = false;
1759. }
1760. }
1761.
1762. // returns a pointer to the first HID device in the list
1763. CHidDevice* CHidManager::GetFirstHidDevice()
1764. {
1765. m_pCurrentHidDevice = m_pHidDeviceListHead;
1766. return m_pCurrentHidDevice;
1767. }
1768.
1769. // returns a pointer to the next HID device in the list
1770. CHidDevice* CHidManager::GetNextHidDevice()
1771. {
1772. if (m_pCurrentHidDevice)
1773. m_pCurrentHidDevice = m_pCurrentHidDevice->nextHidDevice;
1774.
1775. return m_pCurrentHidDevice;
1776. }
1777.
1778. // returns a pointer to the current HID device in the list
1779. CHidDevice* CHidManager::GetCurrentHidDevice()
1780. {
1781. return m_pCurrentHidDevice;
1782. }
1783.
1784. // scans the current list of HID devices and returns a pointer
1785. // to the HID device that matches the device path provided
1786. CHidDevice* CHidManager::GetHidDeviceWithPath(PCHAR pDevicePath)
1787. {
1788. CHidDevice * pCurHidDevice = m_pHidDeviceListHead;
1789.
1790. while (pCurHidDevice)
1791. {
1792. if (!lstrcmpi(pCurHidDevice->m_pHidDevicePath, pDevicePath))
1793. break;
1794.
1795. pCurHidDevice = pCurHidDevice->nextHidDevice;
1796. }
1797.
1798. return pCurHidDevice;
1799. }
1800.
1801. // scans the current list of HID devices and returns a pointer
1802. // to the HID device that matches the device handle provided
1803. CHidDevice* CHidManager::GetHidDeviceWithHandle(HANDLE hHidDevice)
1804. {
1805. CHidDevice * pCurHidDevice = m_pHidDeviceListHead;
1806.
1807. while (pCurHidDevice)
1808. {
1809. if (pCurHidDevice->GetDeviceHandle() == hHidDevice)
1810. break;
1811.
1812. pCurHidDevice = pCurHidDevice->nextHidDevice;
1813. }
1814.
1815. return pCurHidDevice;
1816. }
1817.
1818. // determines if the HID device already exists in the list
1819. bool CHidManager::HidDeviceAlreadyExist(CHidDevice *pHidDevice)
1820. {
1821. CHidDevice * pCurHidDevice = m_pHidDeviceListHead;
1822.
1823. while (pCurHidDevice)
1824. {
1825. if (pCurHidDevice == pHidDevice)
1826. return true;
1827.
1828. pCurHidDevice = pCurHidDevice->nextHidDevice;
1829. }
1830.
1831. return false;
1832. }
1833.
1834. // checks if the provided HID device already exists, and if not,
1835. // adds the new HID device to the end of the list, increments the
1836. // HID device counter, and call the HID callback function to indicate
1837. // a new HID device was added
1838. bool CHidManager::AddHidDevice(CHidDevice *pHidDevice)
1839. {
1840. // determine if HID device already exists
1841. if (HidDeviceAlreadyExist(pHidDevice))
1842. return false;
1843.
1844. // add HID device to end of list, if first device
1845. // then set it as the first device in the list
1846. if (m_pHidDeviceListHead == NULL)
1847. {
1848. m_pHidDeviceListHead = pHidDevice;
1849. }
1850. else
1851. {
1852. CHidDevice * pHidTemp = m_pHidDeviceListHead;
1853.
1854. while (pHidTemp->nextHidDevice != NULL)
1855. {
1856. pHidTemp = pHidTemp->nextHidDevice;
1857. }
1858.
1859. pHidTemp->nextHidDevice = pHidDevice;
1860. }
1861.
1862. // increment HID device counter
1863. m_nHidDevices++;
1864.
1865. // call HID callback function to indicate HID device was added
1866. if (m_pHidCallback) (*m_pHidCallback)(m_pHidCallbackParam, pHidDevice, HIDCB_NOTIFY_DEVICE_ADDED);
1867.
1868. return true;
1869. }
1870.
1871. // closes outstanding handle to the HID device, call HID
1872. // callback function to indicate HID device is being removed,
1873. // removes the HID device from the list, and deletes the HID device
1874. bool CHidManager::RemoveHidDevice(CHidDevice *pHidDevice)
1875. {
1876. // check for valid HID device pointer
1877. if (pHidDevice)
1878. {
1879. // close handle to HID device
1880. pHidDevice->CloseHidDevice();
1881.
1882. CHidDevice * pHidTemp = m_pHidDeviceListHead;
1883. CHidDevice * pHidPrev = NULL;
1884.
1885. // loop through all HID devices in the list to find the
1886. // matching HID device to be removed
1887. while (pHidTemp)
1888. {
1889. // check if HID device was found
1890. if (pHidTemp == pHidDevice)
1891. {
1892. // found, so decrement HID device counter
1893. m_nHidDevices--;
1894.
1895. // call HID callback function to indicate HID device is
1896. // being removed
1897. if (m_pHidCallback) (*m_pHidCallback)(m_pHidCallbackParam, pHidDevice, HIDCB_NOTIFY_DEVICE_REMOVED);
1898.
1899. // remove HID device from list
1900. if (pHidPrev)
1901. {
1902. pHidPrev->nextHidDevice = pHidTemp->nextHidDevice;
1903. }
1904.
1905. if (pHidTemp == m_pHidDeviceListHead)
1906. {
1907. m_pHidDeviceListHead = pHidTemp->nextHidDevice;
1908. }
1909.
1910. // delete HID device
1911. DeleteHidDevice(pHidTemp);
1912.
1913. // end loop
1914. pHidTemp = NULL;
1915. }
1916. else
1917. {
1918. // get next HID device in list
1919. pHidPrev = pHidTemp;
1920. pHidTemp = pHidTemp->nextHidDevice;
1921. }
1922. }
1923. }
1924.
1925. return true;
1926. }
1927.
1928. // scans though all HID devices in the list and removes them
1929. void CHidManager::RemoveAllHidDevices()
1930. {
1931. CHidDevice * pCurHidDevice = m_pHidDeviceListHead;
1932.
1933. while (pCurHidDevice)
1934. {
1935. CHidDevice * pNextHidDevice = pCurHidDevice->nextHidDevice;
1936.
1937. RemoveHidDevice(pCurHidDevice);
1938.
1939. pCurHidDevice = pNextHidDevice;
1940. }
1941.
1942. m_pHidDeviceListHead = NULL;
1943. }
1944.
1945. // validates that all HID devices in the list are still present,
1946. // removes those from the list that are currently not present,
1947. // scans the list of all existing HID devices present, and then
1948. // attempts to add the existing HID devices to the list
1949. bool CHidManager::RefreshHidDevices(void)
1950. {
1951. bool bRetVal = false;
1952. CHidDevice *pCurHidDevice = m_pHidDeviceListHead;
1953.
1954. // first check that all devices are still valid
1955. // remove if not
1956. while (pCurHidDevice)
1957. {
1958. CHidDevice * pNextHidDevice = pCurHidDevice->nextHidDevice;
1959.
1960. if (!IsHidDevicePresent(pCurHidDevice))
1961. {
1962. RemoveHidDevice(pCurHidDevice);
1963. bRetVal = true;
1964. }
1965.
1966. pCurHidDevice = pNextHidDevice;
1967. }
1968.
1969.
1970. // open a handle to the plug and play dev node, SetupDiGetClassDevs()
1971. // returns a device information set that contains info on all installed
1972. // devices of a specified class.
1973. GUID hidGuid;
1974. HDEVINFO hardwareDeviceInfo;
1975. SP_DEVICE_INTERFACE_DATA deviceInfoData;
1976. PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData = NULL;
1977. ULONG predictedLength = 0;
1978. ULONG requiredLength = 0;
1979. ULONG i = 0;
1980. bool bDone = false;
1981.
1982. HidD_GetHidGuid (&hidGuid);
1983.
1984. hardwareDeviceInfo = SetupDiGetClassDevs (&hidGuid,
1985. NULL, // define no enumerator (all HID devices)
1986. NULL, // define no
1987. (DIGCF_PRESENT | // only devices present
1988. DIGCF_INTERFACEDEVICE)); // function class devices.
1989.
1990. if (hardwareDeviceInfo == INVALID_HANDLE_VALUE)
1991. {
1992. // return true to indicate something may have changed
1993. return true;
1994. }
1995.
1996. deviceInfoData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
1997.
1998. while (!bDone)
1999. {
2000. if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
2001. 0, // don't care about specific PDOs
2002. &hidGuid,
2003. i,
2004. &deviceInfoData))
2005. {
2006. //
2007. // allocate a function class device data structure to receive the
2008. // goods about this particular device.
2009.
2010. SetupDiGetDeviceInterfaceDetail (
2011. hardwareDeviceInfo,
2012. &deviceInfoData,
2013. NULL, // probing so no output buffer yet
2014. 0, // probing so output buffer length of zero
2015. &requiredLength,
2016. NULL); // not interested in the specific dev-node
2017.
2018.
2019. predictedLength = requiredLength;
2020.
2021. functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) new UCHAR[predictedLength];
2022. if (functionClassDeviceData)
2023. {
2024. ZeroMemory (functionClassDeviceData, predictedLength);
2025. functionClassDeviceData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
2026. }
2027. else
2028. {
2029. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
2030.
2031. // return true to indicate something may have changed
2032. return true;
2033. }
2034.
2035. //
2036. // retrieve the information from Plug and Play.
2037. //
2038.
2039. if (! SetupDiGetDeviceInterfaceDetail (
2040. hardwareDeviceInfo,
2041. &deviceInfoData,
2042. functionClassDeviceData,
2043. predictedLength,
2044. &requiredLength,
2045. NULL))
2046. {
2047. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
2048. delete [] functionClassDeviceData;
2049.
2050. // return true to indicate something may have changed
2051. return true;
2052. }
2053.
2054. HidDeviceArrival(functionClassDeviceData->DevicePath);
2055.
2056. delete [] functionClassDeviceData;
2057. }
2058. else
2059. {
2060. if (GetLastError() == ERROR_NO_MORE_ITEMS)
2061. {
2062. bDone = true;
2063. }
2064. }
2065.
2066. i++;
2067. }
2068.
2069. return bRetVal;
2070. }
2071.
2072. // makes sure the HID device does not already exist in the list,
2073. // and then creates a new HID device device, opens a handle to
2074. // the device, adds the new HID device to the list, and registers
2075. // event notification for this new HID device
2076. void CHidManager::HidDeviceArrival(PCHAR pDevicePath)
2077. {
2078. // attempt to match a HID device in the list
2079. // based on the device path provided, if not then
2080. // it is okay to add this HID device to the list
2081. // otherwise the HID device already exists in our
2082. // list
2083. if (!GetHidDeviceWithPath(pDevicePath))
2084. {
2085. // this HID device is not in our list, so create
2086. // a new one and attempt to add it to the list
2087. CHidDevice *pNewHidDevice = NewHidDevice(pDevicePath);
2088.
2089. if (pNewHidDevice)
2090. {
2091. // make sure we can open a handle to
2092. // the HID device before we add it
2093. // to the list
2094. if (pNewHidDevice->OpenHidDevice())
2095. {
2096. // handle to the HID device open, so
2097. // now add it to the list and register
2098. // it for event notification
2099. AddHidDevice(pNewHidDevice);
2100. pNewHidDevice->RegisterHidDevice(m_hWnd);
2101. }
2102. else
2103. {
2104. // could not open handle, so just delete
2105. // the HID device craeated
2106. DeleteHidDevice(pNewHidDevice);
2107. }
2108. }
2109. }
2110. }
2111.
2112. // readies the HID device for removal by making sure the handle is closed,
2113. // this version expects the device path
2114. void CHidManager::HidDeviceQueryRemoval(PCHAR pDevicePath)
2115. {
2116. CHidDevice *pHidDevice = GetHidDeviceWithPath(pDevicePath);
2117.
2118. if (pHidDevice)
2119. {
2120. pHidDevice->CloseHidDevice();
2121. }
2122. }
2123.
2124. // readies the HID device for removal by making sure the handle is closed,
2125. // this version expects a handle to the device
2126. void CHidManager::HidDeviceQueryRemoval(HANDLE hHidDevice)
2127. {
2128. CHidDevice *pHidDevice = GetHidDeviceWithHandle(hHidDevice);
2129.
2130. if (pHidDevice)
2131. {
2132. pHidDevice->CloseHidDevice();
2133. }
2134. }
2135.
2136. // removes the HID device, this version expects the
2137. // device path
2138. void CHidManager::HidDeviceRemoval(PCHAR pDevicePath)
2139. {
2140. CHidDevice *pHidDevice = GetHidDeviceWithPath(pDevicePath);
2141.
2142. if (pHidDevice)
2143. {
2144. RemoveHidDevice(pHidDevice);
2145. }
2146. }
2147.
2148. // removes the HID device, this version expects a
2149. // handle to the device
2150. void CHidManager::HidDeviceRemoval(HANDLE hHidDevice)
2151. {
2152. CHidDevice *pHidDevice = GetHidDeviceWithHandle(hHidDevice);
2153.
2154. if (pHidDevice)
2155. {
2156. RemoveHidDevice(pHidDevice);
2157. }
2158. }
2159.
2160. /*
2161. // the global (static) callback function for the CHidManager window
2162. LRESULT PASCAL CHidManager::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
2163. {
2164. CHidManager* pHidManager = m_pThis;
2165.
2166. // make sure our window is the target for this message
2167. if (pHidManager->GetSafeHwnd() == hWnd)
2168. {
2169. if (message == WM_DEVICECHANGE)
2170. {
2171. PDEV_BROADCAST_HDR broadcastHdr = (PDEV_BROADCAST_HDR) lParam;
2172.
2173. if (wParam == DBT_DEVICEARRIVAL)
2174. {
2175. if (broadcastHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
2176. {
2177. PDEV_BROADCAST_DEVICEINTERFACE pBroadcastInterface = (PDEV_BROADCAST_DEVICEINTERFACE) lParam;
2178.
2179. // HID device arrival
2180. pHidManager->HidDeviceArrival(pBroadcastInterface->dbcc_name);
2181. }
2182. }
2183. else if (wParam == DBT_DEVICEQUERYREMOVE)
2184. {
2185. // if this message is received, the device is either
2186. // being disabled or removed through device manager.
2187. // To properly handle this request, we need to close
2188. // the handle to the device.
2189.
2190. if (broadcastHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
2191. {
2192. PDEV_BROADCAST_DEVICEINTERFACE pBroadcastInterface = (PDEV_BROADCAST_DEVICEINTERFACE) lParam;
2193.
2194. // HID device query removal
2195. pHidManager->HidDeviceQueryRemoval(pBroadcastInterface->dbcc_name);
2196. }
2197. else if (broadcastHdr->dbch_devicetype == DBT_DEVTYP_HANDLE)
2198. {
2199. PDEV_BROADCAST_HANDLE pBroadcastDevice = (PDEV_BROADCAST_HANDLE) lParam;
2200.
2201. // HID device query removal
2202. pHidManager->HidDeviceQueryRemoval(pBroadcastDevice->dbch_handle);
2203. }
2204. }
2205. else if ((wParam == DBT_DEVICEREMOVEPENDING) || (wParam == DBT_DEVICEREMOVECOMPLETE))
2206. {
2207. // do the same steps for DBT_DEVICEREMOVEPENDING and
2208. // DBT_DEVICEREMOVECOMPLETE
2209.
2210. // the DBT_DEVICEREMOVECOMPLETE request is not called
2211. // for a device if it is disabled or removed via
2212. // the Device Manager, however, in this case it will
2213. // receive the DBT_DEVICEREMOVEPENDING
2214.
2215. // remove the device from our currently displayed
2216. // list of devices and unregister notification
2217.
2218. if (broadcastHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
2219. {
2220. PDEV_BROADCAST_DEVICEINTERFACE pBroadcastInterface = (PDEV_BROADCAST_DEVICEINTERFACE) lParam;
2221.
2222. // HID device removal
2223. pHidManager->HidDeviceRemoval(pBroadcastInterface->dbcc_name);
2224. }
2225. else if (broadcastHdr->dbch_devicetype == DBT_DEVTYP_HANDLE)
2226. {
2227. PDEV_BROADCAST_HANDLE pBroadcastDevice = (PDEV_BROADCAST_HANDLE) lParam;
2228.
2229. // HID device removal
2230. pHidManager->HidDeviceRemoval(pBroadcastDevice->dbch_handle);
2231. }
2232. }
2233. }
2234. else if (message == WM_UNREGISTER_HANDLE)
2235. {
2236. ::UnregisterDeviceNotification ( (HDEVNOTIFY) lParam );
2237. }
2238. }
2239.
2240. // now the process the message, just default it
2241. return ::DefWindowProc(hWnd, message, wParam, lParam);
2242. }
2243. */ </hidmgr_supported_hid_devices;i++)></dbt.h>
Por otro lado , en la pagina de Cypress Semiconductor hay unos programas , no se si servira alguno de ellos:
http://www.cypress.com/?rID=39531&source=header
Espero que sea algo de ayuda.