code: def close(self):
          
          # free parsed data
          if not self.is_opened():
              return
          self.__open_status = False
  
          # abort all running threads first
          if self.__reading_thread and self.__reading_thread.is_alive():
              self.__reading_thread.abort()
  
          #avoid posting new reports
          if self._input_report_queue:
              self._input_report_queue.release_events()
  
          if self.__input_processing_thread and \
                  self.__input_processing_thread.is_alive():
              self.__input_processing_thread.abort()
  
          #properly close API handlers and pointers
          if self.ptr_preparsed_data:
              ptr_preparsed_data = self.ptr_preparsed_data
              self.ptr_preparsed_data = None
              hid_dll.HidD_FreePreparsedData(ptr_preparsed_data)
  
          # wait for the reading thread to complete before closing device handle
          if self.__reading_thread:
              self.__reading_thread.join()
  
          if self.hid_handle:
              winapi.CloseHandle(self.hid_handle)
  
          # make sure report procesing thread is closed
          if self.__input_processing_thread:
              self.__input_processing_thread.join()
  
          #reset vars (for GC)
          button_caps_storage = self.__button_caps_storage
          self.__reset_vars()
  
          while button_caps_storage:
              item = button_caps_storage.pop()
              del item
docs: Release system resources