SDL  2.0
hid.cpp
Go to the documentation of this file.
1 //=================== Copyright Valve Corporation, All rights reserved. =======
2 //
3 // Purpose: A wrapper implementing "HID" API for Android
4 //
5 // This layer glues the hidapi API to Android's USB and BLE stack.
6 //
7 //=============================================================================
8 
9 #include <jni.h>
10 #include <android/log.h>
11 #include <pthread.h>
12 #include <errno.h> // For ETIMEDOUT and ECONNRESET
13 #include <stdlib.h> // For malloc() and free()
14 #include <string.h> // For memcpy()
15 
16 #define TAG "hidapi"
17 
18 // Have error log always available
19 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
20 
21 #ifdef DEBUG
22 #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
23 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
24 #else
25 #define LOGV(...)
26 #define LOGD(...)
27 #endif
28 
29 #define SDL_JAVA_PREFIX org_libsdl_app
30 #define CONCAT1(prefix, class, function) CONCAT2(prefix, class, function)
31 #define CONCAT2(prefix, class, function) Java_ ## prefix ## _ ## class ## _ ## function
32 #define HID_DEVICE_MANAGER_JAVA_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, HIDDeviceManager, function)
33 
34 #include "../hidapi/hidapi.h"
35 
36 typedef uint32_t uint32;
37 typedef uint64_t uint64;
38 
39 
41 {
42  int m_nId;
44 };
45 
46 static JavaVM *g_JVM;
47 static pthread_key_t g_ThreadKey;
48 
49 template<class T>
51 {
52 public:
53  hid_device_ref( T *pObject = nullptr ) : m_pObject( nullptr )
54  {
55  SetObject( pObject );
56  }
57 
58  hid_device_ref( const hid_device_ref &rhs ) : m_pObject( nullptr )
59  {
60  SetObject( rhs.GetObject() );
61  }
62 
64  {
65  SetObject( nullptr );
66  }
67 
68  void SetObject( T *pObject )
69  {
70  if ( m_pObject && m_pObject->DecrementRefCount() == 0 )
71  {
72  delete m_pObject;
73  }
74 
75  m_pObject = pObject;
76 
77  if ( m_pObject )
78  {
79  m_pObject->IncrementRefCount();
80  }
81  }
82 
83  hid_device_ref &operator =( T *pObject )
84  {
85  SetObject( pObject );
86  return *this;
87  }
88 
89  hid_device_ref &operator =( const hid_device_ref &rhs )
90  {
91  SetObject( rhs.GetObject() );
92  return *this;
93  }
94 
95  T *GetObject() const
96  {
97  return m_pObject;
98  }
99 
100  T* operator->() const
101  {
102  return m_pObject;
103  }
104 
105  operator bool() const
106  {
107  return ( m_pObject != nullptr );
108  }
109 
110 private:
112 };
113 
115 {
116 public:
117  hid_mutex_guard( pthread_mutex_t *pMutex ) : m_pMutex( pMutex )
118  {
119  pthread_mutex_lock( m_pMutex );
120  }
122  {
123  pthread_mutex_unlock( m_pMutex );
124  }
125 
126 private:
127  pthread_mutex_t *m_pMutex;
128 };
129 
131 {
132 public:
133  hid_buffer() : m_pData( nullptr ), m_nSize( 0 ), m_nAllocated( 0 )
134  {
135  }
136 
137  hid_buffer( const uint8_t *pData, size_t nSize ) : m_pData( nullptr ), m_nSize( 0 ), m_nAllocated( 0 )
138  {
139  assign( pData, nSize );
140  }
141 
143  {
144  delete[] m_pData;
145  }
146 
147  void assign( const uint8_t *pData, size_t nSize )
148  {
149  if ( nSize > m_nAllocated )
150  {
151  delete[] m_pData;
152  m_pData = new uint8_t[ nSize ];
153  m_nAllocated = nSize;
154  }
155 
156  m_nSize = nSize;
157  memcpy( m_pData, pData, nSize );
158  }
159 
160  void clear()
161  {
162  m_nSize = 0;
163  }
164 
165  size_t size() const
166  {
167  return m_nSize;
168  }
169 
170  const uint8_t *data() const
171  {
172  return m_pData;
173  }
174 
175 private:
177  size_t m_nSize;
178  size_t m_nAllocated;
179 };
180 
182 {
183 public:
184  hid_buffer_pool() : m_nSize( 0 ), m_pHead( nullptr ), m_pTail( nullptr ), m_pFree( nullptr )
185  {
186  }
187 
189  {
190  clear();
191 
192  while ( m_pFree )
193  {
194  hid_buffer_entry *pEntry = m_pFree;
195  m_pFree = m_pFree->m_pNext;
196  delete pEntry;
197  }
198  }
199 
200  size_t size() const { return m_nSize; }
201 
202  const hid_buffer &front() const { return m_pHead->m_buffer; }
203 
204  void pop_front()
205  {
206  hid_buffer_entry *pEntry = m_pHead;
207  if ( pEntry )
208  {
209  m_pHead = pEntry->m_pNext;
210  if ( !m_pHead )
211  {
212  m_pTail = nullptr;
213  }
214  pEntry->m_pNext = m_pFree;
215  m_pFree = pEntry;
216  --m_nSize;
217  }
218  }
219 
220  void emplace_back( const uint8_t *pData, size_t nSize )
221  {
222  hid_buffer_entry *pEntry;
223 
224  if ( m_pFree )
225  {
226  pEntry = m_pFree;
227  m_pFree = m_pFree->m_pNext;
228  }
229  else
230  {
231  pEntry = new hid_buffer_entry;
232  }
233  pEntry->m_pNext = nullptr;
234 
235  if ( m_pTail )
236  {
237  m_pTail->m_pNext = pEntry;
238  }
239  else
240  {
241  m_pHead = pEntry;
242  }
243  m_pTail = pEntry;
244 
245  pEntry->m_buffer.assign( pData, nSize );
246  ++m_nSize;
247  }
248 
249  void clear()
250  {
251  while ( size() > 0 )
252  {
253  pop_front();
254  }
255  }
256 
257 private:
259  {
262  };
263 
264  size_t m_nSize;
268 };
269 
270 static jbyteArray NewByteArray( JNIEnv* env, const uint8_t *pData, size_t nDataLen )
271 {
272  jbyteArray array = env->NewByteArray( nDataLen );
273  jbyte *pBuf = env->GetByteArrayElements( array, NULL );
274  memcpy( pBuf, pData, nDataLen );
275  env->ReleaseByteArrayElements( array, pBuf, 0 );
276 
277  return array;
278 }
279 
280 static char *CreateStringFromJString( JNIEnv *env, const jstring &sString )
281 {
282  size_t nLength = env->GetStringUTFLength( sString );
283  const char *pjChars = env->GetStringUTFChars( sString, NULL );
284  char *psString = (char*)malloc( nLength + 1 );
285  memcpy( psString, pjChars, nLength );
286  psString[ nLength ] = '\0';
287  env->ReleaseStringUTFChars( sString, pjChars );
288  return psString;
289 }
290 
291 static wchar_t *CreateWStringFromJString( JNIEnv *env, const jstring &sString )
292 {
293  size_t nLength = env->GetStringLength( sString );
294  const jchar *pjChars = env->GetStringChars( sString, NULL );
295  wchar_t *pwString = (wchar_t*)malloc( ( nLength + 1 ) * sizeof( wchar_t ) );
296  wchar_t *pwChars = pwString;
297  for ( size_t iIndex = 0; iIndex < nLength; ++iIndex )
298  {
299  pwChars[ iIndex ] = pjChars[ iIndex ];
300  }
301  pwString[ nLength ] = '\0';
302  env->ReleaseStringChars( sString, pjChars );
303  return pwString;
304 }
305 
306 static wchar_t *CreateWStringFromWString( const wchar_t *pwSrc )
307 {
308  size_t nLength = wcslen( pwSrc );
309  wchar_t *pwString = (wchar_t*)malloc( ( nLength + 1 ) * sizeof( wchar_t ) );
310  memcpy( pwString, pwSrc, nLength * sizeof( wchar_t ) );
311  pwString[ nLength ] = '\0';
312  return pwString;
313 }
314 
316 {
317  hid_device_info *pCopy = new hid_device_info;
318  *pCopy = *pInfo;
319  pCopy->path = strdup( pInfo->path );
323  return pCopy;
324 }
325 
326 static void FreeHIDDeviceInfo( hid_device_info *pInfo )
327 {
328  free( pInfo->path );
329  free( pInfo->serial_number );
330  free( pInfo->manufacturer_string );
331  free( pInfo->product_string );
332  delete pInfo;
333 }
334 
337 static jmethodID g_midHIDDeviceManagerOpen;
341 static jmethodID g_midHIDDeviceManagerClose;
342 
343 static uint64_t get_timespec_ms( const struct timespec &ts )
344 {
345  return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
346 }
347 
349 {
350 public:
351  CHIDDevice( int nDeviceID, hid_device_info *pInfo )
352  {
353  m_nId = nDeviceID;
354  m_pInfo = pInfo;
355 
356  // The Bluetooth Steam Controller needs special handling
357  const int VALVE_USB_VID = 0x28DE;
358  const int D0G_BLE2_PID = 0x1106;
359  if ( pInfo->vendor_id == VALVE_USB_VID && pInfo->product_id == D0G_BLE2_PID )
360  {
361  m_bIsBLESteamController = true;
362  }
363  }
364 
366  {
367  FreeHIDDeviceInfo( m_pInfo );
368 
369  // Note that we don't delete m_pDevice, as the app may still have a reference to it
370  }
371 
373  {
374  int nValue;
375  pthread_mutex_lock( &m_refCountLock );
376  nValue = ++m_nRefCount;
377  pthread_mutex_unlock( &m_refCountLock );
378  return nValue;
379  }
380 
382  {
383  int nValue;
384  pthread_mutex_lock( &m_refCountLock );
385  nValue = --m_nRefCount;
386  pthread_mutex_unlock( &m_refCountLock );
387  return nValue;
388  }
389 
390  int GetId()
391  {
392  return m_nId;
393  }
394 
396  {
397  return m_pInfo;
398  }
399 
400  hid_device *GetDevice()
401  {
402  return m_pDevice;
403  }
404 
405  void ExceptionCheck( JNIEnv *env, const char *pszMethodName )
406  {
407  if ( env->ExceptionCheck() )
408  {
409  // Get our exception
410  jthrowable jExcept = env->ExceptionOccurred();
411 
412  // Clear the exception so we can call JNI again
413  env->ExceptionClear();
414 
415  // Get our exception message
416  jclass jExceptClass = env->GetObjectClass( jExcept );
417  jmethodID jMessageMethod = env->GetMethodID( jExceptClass, "getMessage", "()Ljava/lang/String;" );
418  jstring jMessage = (jstring)( env->CallObjectMethod( jExcept, jMessageMethod ) );
419  const char *pszMessage = env->GetStringUTFChars( jMessage, NULL );
420 
421  // ...and log it.
422  LOGE( "CHIDDevice::%s threw an exception: %s", pszMethodName, pszMessage );
423 
424  // Cleanup
425  env->ReleaseStringUTFChars( jMessage, pszMessage );
426  env->DeleteLocalRef( jMessage );
427  env->DeleteLocalRef( jExceptClass );
428  env->DeleteLocalRef( jExcept );
429  }
430  }
431 
432  bool BOpen()
433  {
434  // Make sure thread is attached to JVM/env
435  JNIEnv *env;
436  g_JVM->AttachCurrentThread( &env, NULL );
437  pthread_setspecific( g_ThreadKey, (void*)env );
438 
439  m_bIsWaitingForOpen = false;
440  m_bOpenResult = env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerOpen, m_nId );
441  ExceptionCheck( env, "BOpen" );
442 
443  if ( m_bIsWaitingForOpen )
444  {
445  hid_mutex_guard cvl( &m_cvLock );
446 
447  const int OPEN_TIMEOUT_SECONDS = 60;
448  struct timespec ts, endtime;
449  clock_gettime( CLOCK_REALTIME, &ts );
450  endtime = ts;
451  endtime.tv_sec += OPEN_TIMEOUT_SECONDS;
452  do
453  {
454  if ( pthread_cond_timedwait( &m_cv, &m_cvLock, &endtime ) != 0 )
455  {
456  break;
457  }
458  }
459  while ( m_bIsWaitingForOpen && get_timespec_ms( ts ) < get_timespec_ms( endtime ) );
460  }
461 
462  if ( !m_bOpenResult )
463  {
464  if ( m_bIsWaitingForOpen )
465  {
466  LOGV( "Device open failed - timed out waiting for device permission" );
467  }
468  else
469  {
470  LOGV( "Device open failed" );
471  }
472  return false;
473  }
474 
475  m_pDevice = new hid_device;
476  m_pDevice->m_nId = m_nId;
477  m_pDevice->m_nDeviceRefCount = 1;
478  LOGD("Creating device %d (%p), refCount = 1\n", m_pDevice->m_nId, m_pDevice);
479  return true;
480  }
481 
483  {
484  m_bIsWaitingForOpen = true;
485  }
486 
487  void SetOpenResult( bool bResult )
488  {
489  if ( m_bIsWaitingForOpen )
490  {
491  m_bOpenResult = bResult;
492  m_bIsWaitingForOpen = false;
493  pthread_cond_signal( &m_cv );
494  }
495  }
496 
497  void ProcessInput( const uint8_t *pBuf, size_t nBufSize )
498  {
499  hid_mutex_guard l( &m_dataLock );
500 
501  size_t MAX_REPORT_QUEUE_SIZE = 16;
502  if ( m_vecData.size() >= MAX_REPORT_QUEUE_SIZE )
503  {
504  m_vecData.pop_front();
505  }
506  m_vecData.emplace_back( pBuf, nBufSize );
507  }
508 
509  int GetInput( unsigned char *data, size_t length )
510  {
511  hid_mutex_guard l( &m_dataLock );
512 
513  if ( m_vecData.size() == 0 )
514  {
515 // LOGV( "hid_read_timeout no data available" );
516  return 0;
517  }
518 
519  const hid_buffer &buffer = m_vecData.front();
520  size_t nDataLen = buffer.size() > length ? length : buffer.size();
521  if ( m_bIsBLESteamController )
522  {
523  data[0] = 0x03;
524  memcpy( data + 1, buffer.data(), nDataLen );
525  ++nDataLen;
526  }
527  else
528  {
529  memcpy( data, buffer.data(), nDataLen );
530  }
531  m_vecData.pop_front();
532 
533 // LOGV("Read %u bytes", nDataLen);
534 // LOGV("%02x %02x %02x %02x %02x %02x %02x %02x ....",
535 // data[0], data[1], data[2], data[3],
536 // data[4], data[5], data[6], data[7]);
537 
538  return nDataLen;
539  }
540 
541  int SendOutputReport( const unsigned char *pData, size_t nDataLen )
542  {
543  // Make sure thread is attached to JVM/env
544  JNIEnv *env;
545  g_JVM->AttachCurrentThread( &env, NULL );
546  pthread_setspecific( g_ThreadKey, (void*)env );
547 
548  jbyteArray pBuf = NewByteArray( env, pData, nDataLen );
549  int nRet = env->CallIntMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerSendOutputReport, m_nId, pBuf );
550  ExceptionCheck( env, "SendOutputReport" );
551 
552  env->DeleteLocalRef( pBuf );
553  return nRet;
554  }
555 
556  int SendFeatureReport( const unsigned char *pData, size_t nDataLen )
557  {
558  // Make sure thread is attached to JVM/env
559  JNIEnv *env;
560  g_JVM->AttachCurrentThread( &env, NULL );
561  pthread_setspecific( g_ThreadKey, (void*)env );
562 
563  jbyteArray pBuf = NewByteArray( env, pData, nDataLen );
564  int nRet = env->CallIntMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerSendFeatureReport, m_nId, pBuf );
565  ExceptionCheck( env, "SendFeatureReport" );
566  env->DeleteLocalRef( pBuf );
567  return nRet;
568  }
569 
570  void ProcessFeatureReport( const uint8_t *pBuf, size_t nBufSize )
571  {
572  hid_mutex_guard cvl( &m_cvLock );
573  if ( m_bIsWaitingForFeatureReport )
574  {
575  m_featureReport.assign( pBuf, nBufSize );
576 
577  m_bIsWaitingForFeatureReport = false;
578  m_nFeatureReportError = 0;
579  pthread_cond_signal( &m_cv );
580  }
581  }
582 
583  int GetFeatureReport( unsigned char *pData, size_t nDataLen )
584  {
585  // Make sure thread is attached to JVM/env
586  JNIEnv *env;
587  g_JVM->AttachCurrentThread( &env, NULL );
588  pthread_setspecific( g_ThreadKey, (void*)env );
589 
590  {
591  hid_mutex_guard cvl( &m_cvLock );
592  if ( m_bIsWaitingForFeatureReport )
593  {
594  LOGV( "Get feature report already ongoing... bail" );
595  return -1; // Read already ongoing, we currently do not serialize, TODO
596  }
597  m_bIsWaitingForFeatureReport = true;
598  }
599 
600  jbyteArray pBuf = NewByteArray( env, pData, nDataLen );
601  int nRet = env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerGetFeatureReport, m_nId, pBuf ) ? 0 : -1;
602  ExceptionCheck( env, "GetFeatureReport" );
603  env->DeleteLocalRef( pBuf );
604  if ( nRet < 0 )
605  {
606  LOGV( "GetFeatureReport failed" );
607  m_bIsWaitingForFeatureReport = false;
608  return -1;
609  }
610 
611  {
612  hid_mutex_guard cvl( &m_cvLock );
613  if ( m_bIsWaitingForFeatureReport )
614  {
615  LOGV("=== Going to sleep" );
616  // Wait in CV until we are no longer waiting for a feature report.
617  const int FEATURE_REPORT_TIMEOUT_SECONDS = 2;
618  struct timespec ts, endtime;
619  clock_gettime( CLOCK_REALTIME, &ts );
620  endtime = ts;
621  endtime.tv_sec += FEATURE_REPORT_TIMEOUT_SECONDS;
622  do
623  {
624  if ( pthread_cond_timedwait( &m_cv, &m_cvLock, &endtime ) != 0 )
625  {
626  break;
627  }
628  }
629  while ( m_bIsWaitingForFeatureReport && get_timespec_ms( ts ) < get_timespec_ms( endtime ) );
630 
631  // We are back
632  if ( m_bIsWaitingForFeatureReport )
633  {
634  m_nFeatureReportError = -ETIMEDOUT;
635  m_bIsWaitingForFeatureReport = false;
636  }
637  LOGV( "=== Got feature report err=%d", m_nFeatureReportError );
638  if ( m_nFeatureReportError != 0 )
639  {
640  return m_nFeatureReportError;
641  }
642  }
643 
644  size_t uBytesToCopy = m_featureReport.size() > nDataLen ? nDataLen : m_featureReport.size();
645  memcpy( pData, m_featureReport.data(), uBytesToCopy );
646  m_featureReport.clear();
647  LOGV( "=== Got %u bytes", uBytesToCopy );
648 
649  return uBytesToCopy;
650  }
651  }
652 
653  void Close( bool bDeleteDevice )
654  {
655  // Make sure thread is attached to JVM/env
656  JNIEnv *env;
657  g_JVM->AttachCurrentThread( &env, NULL );
658  pthread_setspecific( g_ThreadKey, (void*)env );
659 
661  ExceptionCheck( env, "Close" );
662 
663  hid_mutex_guard dataLock( &m_dataLock );
664  m_vecData.clear();
665 
666  // Clean and release pending feature report reads
667  hid_mutex_guard cvLock( &m_cvLock );
668  m_featureReport.clear();
669  m_bIsWaitingForFeatureReport = false;
670  m_nFeatureReportError = -ECONNRESET;
671  pthread_cond_broadcast( &m_cv );
672 
673  if ( bDeleteDevice )
674  {
675  delete m_pDevice;
676  m_pDevice = nullptr;
677  }
678  }
679 
680 private:
681  pthread_mutex_t m_refCountLock = PTHREAD_MUTEX_INITIALIZER;
682  int m_nRefCount = 0;
683  int m_nId = 0;
684  hid_device_info *m_pInfo = nullptr;
685  hid_device *m_pDevice = nullptr;
686  bool m_bIsBLESteamController = false;
687 
688  pthread_mutex_t m_dataLock = PTHREAD_MUTEX_INITIALIZER; // This lock has to be held to access m_vecData
690 
691  // For handling get_feature_report
692  pthread_mutex_t m_cvLock = PTHREAD_MUTEX_INITIALIZER; // This lock has to be held to access any variables below
693  pthread_cond_t m_cv = PTHREAD_COND_INITIALIZER;
694  bool m_bIsWaitingForOpen = false;
695  bool m_bOpenResult = false;
696  bool m_bIsWaitingForFeatureReport = false;
697  int m_nFeatureReportError = 0;
699 
700 public:
702 };
703 
704 class CHIDDevice;
705 static pthread_mutex_t g_DevicesMutex = PTHREAD_MUTEX_INITIALIZER;
706 static pthread_mutex_t g_DevicesRefCountMutex = PTHREAD_MUTEX_INITIALIZER;
708 
709 static hid_device_ref<CHIDDevice> FindDevice( int nDeviceId )
710 {
712 
714  for ( pDevice = g_Devices; pDevice; pDevice = pDevice->next )
715  {
716  if ( pDevice->GetId() == nDeviceId )
717  {
718  break;
719  }
720  }
721  return pDevice;
722 }
723 
724 static void ThreadDestroyed(void* value)
725 {
726  /* The thread is being destroyed, detach it from the Java VM and set the g_ThreadKey value to NULL as required */
727  JNIEnv *env = (JNIEnv*) value;
728  if (env != NULL) {
729  g_JVM->DetachCurrentThread();
730  pthread_setspecific(g_ThreadKey, NULL);
731  }
732 }
733 
734 
735 extern "C"
736 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceRegisterCallback)(JNIEnv *env, jobject thiz);
737 
738 extern "C"
739 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz);
740 
741 extern "C"
742 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface );
743 
744 extern "C"
745 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID);
746 
747 extern "C"
748 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenResult)(JNIEnv *env, jobject thiz, int nDeviceID, bool bOpened);
749 
750 extern "C"
751 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceDisconnected)(JNIEnv *env, jobject thiz, int nDeviceID);
752 
753 extern "C"
754 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceInputReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value);
755 
756 extern "C"
757 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceFeatureReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value);
758 
759 
760 extern "C"
761 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceRegisterCallback)(JNIEnv *env, jobject thiz )
762 {
763  LOGV( "HIDDeviceRegisterCallback()");
764 
765  env->GetJavaVM( &g_JVM );
766 
767  /*
768  * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
769  * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
770  */
771  if (pthread_key_create(&g_ThreadKey, ThreadDestroyed) != 0) {
772  __android_log_print(ANDROID_LOG_ERROR, TAG, "Error initializing pthread key");
773  }
774 
776  {
777  env->DeleteGlobalRef( g_HIDDeviceManagerCallbackClass );
779  env->DeleteGlobalRef( g_HIDDeviceManagerCallbackHandler );
781  }
782 
783  g_HIDDeviceManagerCallbackHandler = env->NewGlobalRef( thiz );
784  jclass objClass = env->GetObjectClass( thiz );
785  if ( objClass )
786  {
787  g_HIDDeviceManagerCallbackClass = reinterpret_cast< jclass >( env->NewGlobalRef( objClass ) );
788  g_midHIDDeviceManagerOpen = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "openDevice", "(I)Z" );
790  {
791  __android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing openDevice" );
792  }
793  g_midHIDDeviceManagerSendOutputReport = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "sendOutputReport", "(I[B)I" );
795  {
796  __android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing sendOutputReport" );
797  }
798  g_midHIDDeviceManagerSendFeatureReport = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "sendFeatureReport", "(I[B)I" );
800  {
801  __android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing sendFeatureReport" );
802  }
803  g_midHIDDeviceManagerGetFeatureReport = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "getFeatureReport", "(I[B)Z" );
805  {
806  __android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing getFeatureReport" );
807  }
808  g_midHIDDeviceManagerClose = env->GetMethodID( g_HIDDeviceManagerCallbackClass, "closeDevice", "(I)V" );
810  {
811  __android_log_print(ANDROID_LOG_ERROR, TAG, "HIDDeviceRegisterCallback: callback class missing closeDevice" );
812  }
813  env->DeleteLocalRef( objClass );
814  }
815 }
816 
817 extern "C"
818 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz)
819 {
820  LOGV("HIDDeviceReleaseCallback");
821  if ( env->IsSameObject( thiz, g_HIDDeviceManagerCallbackHandler ) )
822  {
823  env->DeleteGlobalRef( g_HIDDeviceManagerCallbackClass );
825  env->DeleteGlobalRef( g_HIDDeviceManagerCallbackHandler );
827  }
828 }
829 
830 extern "C"
831 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface )
832 {
833  LOGV( "HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface );
834 
835  hid_device_info *pInfo = new hid_device_info;
836  memset( pInfo, 0, sizeof( *pInfo ) );
837  pInfo->path = CreateStringFromJString( env, sIdentifier );
838  pInfo->vendor_id = nVendorId;
839  pInfo->product_id = nProductId;
840  pInfo->serial_number = CreateWStringFromJString( env, sSerialNumber );
841  pInfo->release_number = nReleaseNumber;
842  pInfo->manufacturer_string = CreateWStringFromJString( env, sManufacturer );
843  pInfo->product_string = CreateWStringFromJString( env, sProduct );
844  pInfo->interface_number = nInterface;
845 
846  hid_device_ref<CHIDDevice> pDevice( new CHIDDevice( nDeviceID, pInfo ) );
847 
849  hid_device_ref<CHIDDevice> pLast, pCurr;
850  for ( pCurr = g_Devices; pCurr; pLast = pCurr, pCurr = pCurr->next )
851  {
852  continue;
853  }
854  if ( pLast )
855  {
856  pLast->next = pDevice;
857  }
858  else
859  {
860  g_Devices = pDevice;
861  }
862 }
863 
864 extern "C"
865 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID)
866 {
867  LOGV( "HIDDeviceOpenPending() id=%d\n", nDeviceID );
868  hid_device_ref<CHIDDevice> pDevice = FindDevice( nDeviceID );
869  if ( pDevice )
870  {
871  pDevice->SetOpenPending();
872  }
873 }
874 
875 extern "C"
876 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenResult)(JNIEnv *env, jobject thiz, int nDeviceID, bool bOpened)
877 {
878  LOGV( "HIDDeviceOpenResult() id=%d, result=%s\n", nDeviceID, bOpened ? "true" : "false" );
879  hid_device_ref<CHIDDevice> pDevice = FindDevice( nDeviceID );
880  if ( pDevice )
881  {
882  pDevice->SetOpenResult( bOpened );
883  }
884 }
885 
886 extern "C"
887 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceDisconnected)(JNIEnv *env, jobject thiz, int nDeviceID)
888 {
889  LOGV( "HIDDeviceDisconnected() id=%d\n", nDeviceID );
891  {
893  hid_device_ref<CHIDDevice> pLast, pCurr;
894  for ( pCurr = g_Devices; pCurr; pLast = pCurr, pCurr = pCurr->next )
895  {
896  if ( pCurr->GetId() == nDeviceID )
897  {
898  pDevice = pCurr;
899 
900  if ( pLast )
901  {
902  pLast->next = pCurr->next;
903  }
904  else
905  {
906  g_Devices = pCurr->next;
907  }
908  }
909  }
910  }
911  if ( pDevice )
912  {
913  pDevice->Close( false );
914  }
915 }
916 
917 extern "C"
918 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceInputReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value)
919 {
920  jbyte *pBuf = env->GetByteArrayElements(value, NULL);
921  jsize nBufSize = env->GetArrayLength(value);
922 
923 // LOGV( "HIDDeviceInput() id=%d len=%u\n", nDeviceID, nBufSize );
924  hid_device_ref<CHIDDevice> pDevice = FindDevice( nDeviceID );
925  if ( pDevice )
926  {
927  pDevice->ProcessInput( reinterpret_cast< const uint8_t* >( pBuf ), nBufSize );
928  }
929 
930  env->ReleaseByteArrayElements(value, pBuf, 0);
931 }
932 
933 extern "C"
934 JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceFeatureReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value)
935 {
936  jbyte *pBuf = env->GetByteArrayElements(value, NULL);
937  jsize nBufSize = env->GetArrayLength(value);
938 
939  LOGV( "HIDDeviceFeatureReport() id=%d len=%u\n", nDeviceID, nBufSize );
940  hid_device_ref<CHIDDevice> pDevice = FindDevice( nDeviceID );
941  if ( pDevice )
942  {
943  pDevice->ProcessFeatureReport( reinterpret_cast< const uint8_t* >( pBuf ), nBufSize );
944  }
945 
946  env->ReleaseByteArrayElements(value, pBuf, 0);
947 }
948 
949 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
950 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
951 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
952 
953 extern "C"
954 {
955 
956 int hid_init(void)
957 {
958  return 0;
959 }
960 
962 {
963  struct hid_device_info *root = NULL;
965  for ( hid_device_ref<CHIDDevice> pDevice = g_Devices; pDevice; pDevice = pDevice->next )
966  {
967  const hid_device_info *info = pDevice->GetDeviceInfo();
968  if ( ( vendor_id == 0 && product_id == 0 ) ||
969  ( vendor_id == info->vendor_id && product_id == info->product_id ) )
970  {
971  hid_device_info *dev = CopyHIDDeviceInfo( info );
972  dev->next = root;
973  root = dev;
974  }
975  }
976  return root;
977 }
978 
980 {
981  while ( devs )
982  {
983  struct hid_device_info *next = devs->next;
984  FreeHIDDeviceInfo( devs );
985  devs = next;
986  }
987 }
988 
989 HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
990 {
991  // TODO: Implement
992  return NULL;
993 }
994 
995 HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive)
996 {
997  LOGV( "hid_open_path( %s )", path );
998 
1000  {
1003  for ( hid_device_ref<CHIDDevice> pCurr = g_Devices; pCurr; pCurr = pCurr->next )
1004  {
1005  if ( strcmp( pCurr->GetDeviceInfo()->path, path ) == 0 )
1006  {
1007  hid_device *pValue = pCurr->GetDevice();
1008  if ( pValue )
1009  {
1010  ++pValue->m_nDeviceRefCount;
1011  LOGD("Incrementing device %d (%p), refCount = %d\n", pValue->m_nId, pValue, pValue->m_nDeviceRefCount);
1012  return pValue;
1013  }
1014 
1015  // Hold a shared pointer to the controller for the duration
1016  pDevice = pCurr;
1017  break;
1018  }
1019  }
1020  }
1021  if ( pDevice && pDevice->BOpen() )
1022  {
1023  return pDevice->GetDevice();
1024  }
1025  return NULL;
1026 }
1027 
1028 int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
1029 {
1030  LOGV( "hid_write id=%d length=%u", device->m_nId, length );
1031  hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
1032  if ( pDevice )
1033  {
1034  return pDevice->SendOutputReport( data, length );
1035  }
1036  return -1; // Controller was disconnected
1037 }
1038 
1039 // TODO: Implement timeout?
1040 int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
1041 {
1042 // LOGV( "hid_read_timeout id=%d length=%u timeout=%d", device->m_nId, length, milliseconds );
1043  hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
1044  if ( pDevice )
1045  {
1046  return pDevice->GetInput( data, length );
1047  }
1048  LOGV( "controller was disconnected" );
1049  return -1; // Controller was disconnected
1050 }
1051 
1052 // TODO: Implement blocking
1053 int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
1054 {
1055  LOGV( "hid_read id=%d length=%u", device->m_nId, length );
1056  return hid_read_timeout( device, data, length, 0 );
1057 }
1058 
1059 // TODO: Implement?
1061 {
1062  return -1;
1063 }
1064 
1065 int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
1066 {
1067  LOGV( "hid_send_feature_report id=%d length=%u", device->m_nId, length );
1068  hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
1069  if ( pDevice )
1070  {
1071  return pDevice->SendFeatureReport( data, length );
1072  }
1073  return -1; // Controller was disconnected
1074 }
1075 
1076 
1077 // Synchronous operation. Will block until completed.
1078 int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
1079 {
1080  LOGV( "hid_get_feature_report id=%d length=%u", device->m_nId, length );
1081  hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
1082  if ( pDevice )
1083  {
1084  return pDevice->GetFeatureReport( data, length );
1085  }
1086  return -1; // Controller was disconnected
1087 }
1088 
1089 
1091 {
1092  LOGV( "hid_close id=%d", device->m_nId );
1094  LOGD("Decrementing device %d (%p), refCount = %d\n", device->m_nId, device, device->m_nDeviceRefCount - 1);
1095  if ( --device->m_nDeviceRefCount == 0 )
1096  {
1097  hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
1098  if ( pDevice )
1099  {
1100  pDevice->Close( true );
1101  }
1102  else
1103  {
1104  delete device;
1105  }
1106  LOGD("Deleted device %p\n", device);
1107  }
1108 
1109 }
1110 
1111 int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
1112 {
1113  hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
1114  if ( pDevice )
1115  {
1116  wcsncpy( string, pDevice->GetDeviceInfo()->manufacturer_string, maxlen );
1117  return 0;
1118  }
1119  return -1;
1120 }
1121 
1122 int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
1123 {
1124  hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
1125  if ( pDevice )
1126  {
1127  wcsncpy( string, pDevice->GetDeviceInfo()->product_string, maxlen );
1128  return 0;
1129  }
1130  return -1;
1131 }
1132 
1133 int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
1134 {
1135  hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
1136  if ( pDevice )
1137  {
1138  wcsncpy( string, pDevice->GetDeviceInfo()->serial_number, maxlen );
1139  return 0;
1140  }
1141  return -1;
1142 }
1143 
1144 int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
1145 {
1146  return -1;
1147 }
1148 
1149 HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
1150 {
1151  return NULL;
1152 }
1153 
1154 int hid_exit(void)
1155 {
1156  return 0;
1157 }
1158 
1159 }
#define HID_DEVICE_MANAGER_JAVA_INTERFACE(function)
Definition: hid.cpp:32
HID_API_EXPORT const wchar_t *HID_API_CALL hid_error(hid_device *device)
Get a string describing the last error which occurred.
Definition: hid.cpp:1149
~hid_buffer_pool()
Definition: hid.cpp:188
int GetInput(unsigned char *data, size_t length)
Definition: hid.cpp:509
static jmethodID g_midHIDDeviceManagerOpen
Definition: hid.cpp:337
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
uint32_t uint32
Definition: hid.cpp:36
int interface_number
Definition: hidapi.h:79
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE() HIDDeviceReleaseCallback(JNIEnv *env, jobject thiz)
Definition: hid.cpp:818
static JavaVM * g_JVM
Definition: hid.cpp:46
static jmethodID g_midHIDDeviceManagerGetFeatureReport
Definition: hid.cpp:340
const uint8_t * data() const
Definition: hid.cpp:170
void assign(const uint8_t *pData, size_t nSize)
Definition: hid.cpp:147
hid_buffer(const uint8_t *pData, size_t nSize)
Definition: hid.cpp:137
#define HID_API_EXPORT
Definition: hidapi.h:36
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
Definition: hid.cpp:979
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE() HIDDeviceOpenPending(JNIEnv *env, jobject thiz, int nDeviceID)
Definition: hid.cpp:865
const hid_device_info * GetDeviceInfo()
Definition: hid.cpp:395
hid_buffer_pool()
Definition: hid.cpp:184
SDL_EventEntry * free
Definition: SDL_events.c:84
hid_buffer m_buffer
Definition: hid.cpp:260
void ExceptionCheck(JNIEnv *env, const char *pszMethodName)
Definition: hid.cpp:405
unsigned long long uint64_t
#define memset
Definition: SDL_malloc.c:619
hid_buffer_entry * m_pHead
Definition: hid.cpp:265
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE() HIDDeviceRegisterCallback(JNIEnv *env, jobject thiz)
Definition: hid.cpp:761
T * m_pObject
Definition: hid.cpp:111
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
hid_buffer m_featureReport
Definition: hid.cpp:698
static jobject g_HIDDeviceManagerCallbackHandler
Definition: hid.cpp:336
static jmethodID g_midHIDDeviceManagerSendOutputReport
Definition: hid.cpp:338
hid_device_ref< CHIDDevice > next
Definition: hid.cpp:701
bool BOpen()
Definition: hid.cpp:432
const hid_buffer & front() const
Definition: hid.cpp:202
wchar_t * manufacturer_string
Definition: hidapi.h:66
int SendFeatureReport(const unsigned char *pData, size_t nDataLen)
Definition: hid.cpp:556
hid_buffer_entry * m_pTail
Definition: hid.cpp:266
hid_device * GetDevice()
Definition: hid.cpp:400
int m_nDeviceRefCount
Definition: hid.cpp:43
char * path
Definition: hidapi.h:55
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
Definition: hid.cpp:1028
static pthread_mutex_t g_DevicesRefCountMutex
Definition: hid.cpp:706
static jmethodID g_midHIDDeviceManagerClose
Definition: hid.cpp:341
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
Get a string from a HID device, based on its string index.
Definition: hid.cpp:1144
hid_device_ref(T *pObject=nullptr)
Definition: hid.cpp:53
static const double T[]
Definition: k_tan.c:53
static pthread_mutex_t g_DevicesMutex
Definition: hid.cpp:705
static SDL_AudioDeviceID device
Definition: loopwave.c:37
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
Definition: hid.cpp:1040
static hid_device_ref< CHIDDevice > g_Devices
Definition: hid.cpp:707
struct hid_device_info * next
Definition: hidapi.h:82
void Close(bool bDeleteDevice)
Definition: hid.cpp:653
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
Set the device handle to be non-blocking.
Definition: hid.cpp:1060
size_t m_nAllocated
Definition: hid.cpp:178
hid_buffer_entry * m_pNext
Definition: hid.cpp:261
void ProcessFeatureReport(const uint8_t *pBuf, size_t nBufSize)
Definition: hid.cpp:570
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
Definition: hid.cpp:1090
static jmethodID g_midHIDDeviceManagerSendFeatureReport
Definition: hid.cpp:339
T * operator->() const
Definition: hid.cpp:100
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Product String from a HID device.
Definition: hid.cpp:1122
void clear()
Definition: hid.cpp:249
size_t size() const
Definition: hid.cpp:200
int GetFeatureReport(unsigned char *pData, size_t nDataLen)
Definition: hid.cpp:583
unsigned short product_id
Definition: hidapi.h:59
static void ThreadDestroyed(void *value)
Definition: hid.cpp:724
pthread_mutex_t * m_pMutex
Definition: hid.cpp:127
static void FreeHIDDeviceInfo(hid_device_info *pInfo)
Definition: hid.cpp:326
wchar_t * serial_number
Definition: hidapi.h:61
CHIDDevice(int nDeviceID, hid_device_info *pInfo)
Definition: hid.cpp:351
int hid_exit(void)
Finalize the HIDAPI library.
Definition: hid.cpp:1154
static char * CreateStringFromJString(JNIEnv *env, const jstring &sString)
Definition: hid.cpp:280
unsigned short vendor_id
Definition: hidapi.h:57
HID_API_EXPORT hid_device *HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally a serial number...
Definition: hid.cpp:989
static hid_device_info * CopyHIDDeviceInfo(const hid_device_info *pInfo)
Definition: hid.cpp:315
void clear()
Definition: hid.cpp:160
GLsizei const GLfloat * value
void emplace_back(const uint8_t *pData, size_t nSize)
Definition: hid.cpp:220
hid_buffer_entry * m_pFree
Definition: hid.cpp:267
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
Get a feature report from a HID device.
Definition: hid.cpp:1078
wchar_t * product_string
Definition: hidapi.h:68
void SetObject(T *pObject)
Definition: hid.cpp:68
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Serial Number String from a HID device.
Definition: hid.cpp:1133
~hid_mutex_guard()
Definition: hid.cpp:121
GLsizeiptr size
size_t m_nSize
Definition: hid.cpp:177
~hid_device_ref()
Definition: hid.cpp:63
#define HID_API_EXPORT_CALL
Definition: hidapi.h:40
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE() HIDDeviceInputReport(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value)
Definition: hid.cpp:918
uint8_t * m_pData
Definition: hid.cpp:176
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE() HIDDeviceDisconnected(JNIEnv *env, jobject thiz, int nDeviceID)
Definition: hid.cpp:887
int SendOutputReport(const unsigned char *pData, size_t nDataLen)
Definition: hid.cpp:541
hid_device_ref(const hid_device_ref &rhs)
Definition: hid.cpp:58
#define NULL
Definition: begin_code.h:164
GLuint buffer
void SetOpenResult(bool bResult)
Definition: hid.cpp:487
Definition: hid.cpp:258
unsigned char uint8_t
unsigned int uint32_t
hid_buffer_pool m_vecData
Definition: hid.cpp:689
int GetId()
Definition: hid.cpp:390
void pop_front()
Definition: hid.cpp:204
void SetOpenPending()
Definition: hid.cpp:482
size_t m_nSize
Definition: hid.cpp:264
int hid_init(void)
Initialize the HIDAPI library.
Definition: hid.cpp:956
int IncrementRefCount()
Definition: hid.cpp:372
~hid_buffer()
Definition: hid.cpp:142
static pthread_key_t g_ThreadKey
Definition: hid.cpp:47
#define LOGV(...)
Definition: hid.cpp:25
#define memcpy
Definition: SDL_malloc.c:622
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE() HIDDeviceOpenResult(JNIEnv *env, jobject thiz, int nDeviceID, bool bOpened)
Definition: hid.cpp:876
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE() HIDDeviceFeatureReport(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value)
Definition: hid.cpp:934
static uint64_t get_timespec_ms(const struct timespec &ts)
Definition: hid.cpp:343
void ProcessInput(const uint8_t *pBuf, size_t nBufSize)
Definition: hid.cpp:497
int m_nId
Definition: hid.cpp:42
static jbyteArray NewByteArray(JNIEnv *env, const uint8_t *pData, size_t nDataLen)
Definition: hid.cpp:270
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
Definition: hid.cpp:995
#define LOGD(...)
Definition: hid.cpp:26
GLenum array
#define TAG
Definition: hid.cpp:16
GLsizei const GLchar *const * path
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
Send a Feature report to the device.
Definition: hid.cpp:1065
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Manufacturer String from a HID device.
Definition: hid.cpp:1111
GLuint GLsizei GLsizei * length
~CHIDDevice()
Definition: hid.cpp:365
static jclass g_HIDDeviceManagerCallbackClass
Definition: hid.cpp:335
static wchar_t * CreateWStringFromWString(const wchar_t *pwSrc)
Definition: hid.cpp:306
static hid_device_ref< CHIDDevice > FindDevice(int nDeviceId)
Definition: hid.cpp:709
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
Enumerate the HID Devices.
Definition: hid.cpp:961
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE() HIDDeviceConnected(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface)
Definition: hid.cpp:831
#define LOGE(...)
Definition: hid.cpp:19
#define HID_API_CALL
Definition: hidapi.h:37
#define malloc
Definition: SDL_qsort.c:47
unsigned short release_number
Definition: hidapi.h:64
static wchar_t * CreateWStringFromJString(JNIEnv *env, const jstring &sString)
Definition: hid.cpp:291
uint64_t uint64
Definition: hid.cpp:37
hid_mutex_guard(pthread_mutex_t *pMutex)
Definition: hid.cpp:117
hid_buffer()
Definition: hid.cpp:133
int DecrementRefCount()
Definition: hid.cpp:381
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
Read an Input report from a HID device.
Definition: hid.cpp:1053
T * GetObject() const
Definition: hid.cpp:95
size_t size() const
Definition: hid.cpp:165