Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
usb_hid.py
00001 # 00002 # DAPLink Interface Firmware 00003 # Copyright (c) 2016-2016, ARM Limited, All Rights Reserved 00004 # SPDX-License-Identifier: Apache-2.0 00005 # 00006 # Licensed under the Apache License, Version 2.0 (the "License"); you may 00007 # not use this file except in compliance with the License. 00008 # You may obtain a copy of the License at 00009 # 00010 # http://www.apache.org/licenses/LICENSE-2.0 00011 # 00012 # Unless required by applicable law or agreed to in writing, software 00013 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00014 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 # See the License for the specific language governing permissions and 00016 # limitations under the License. 00017 # 00018 00019 import usb.util 00020 00021 00022 class USBHid (object): 00023 """Wrapper class for a HID usb device""" 00024 00025 # HID commands documented in 00026 # Device Class Definition for Human Interface Devices (HID) 00027 00028 CLASS_HID = 0x3 00029 00030 DESC_TYPE_HID = 0x21 00031 DESC_TYPE_REPORT = 0x22 00032 DESC_TYPE_PHYSICAL = 0x23 00033 00034 REPORT_TYPE_INPUT = 1 00035 REPORT_TYPE_OUTPUT = 2 00036 REPORT_TYPE_FEATURE = 3 00037 00038 def __init__(self, device): 00039 self._dev = device 00040 self._if = None 00041 self.ep_in = None 00042 self.ep_out = None 00043 self._locked = False 00044 self.timeout = 10 * 1000 00045 00046 # Find interface 00047 for interface in device.get_active_configuration(): 00048 if interface.bInterfaceClass == USBHid.CLASS_HID: 00049 assert self._if is None 00050 self._if = interface 00051 assert self._if is not None 00052 00053 # Find endpoints 00054 for endpoint in self._if : 00055 if endpoint.bEndpointAddress & 0x80: 00056 assert self.ep_in is None 00057 self.ep_in = endpoint 00058 else: 00059 assert self.ep_out is None 00060 self.ep_out = endpoint 00061 assert self.ep_in is not None 00062 # Endpoint out can be None 00063 00064 def lock (self): 00065 """Acquire exclisive access to HID""" 00066 assert not self._locked 00067 00068 num = self._if .bInterfaceNumber 00069 try: 00070 if self._dev .is_kernel_driver_active(num): 00071 self._dev .detach_kernel_driver(num) 00072 except NotImplementedError: 00073 pass 00074 except usb.core.USBError: 00075 pass 00076 usb.util.claim_interface(self._dev , num) 00077 self._locked = True 00078 00079 def unlock (self): 00080 """Release exclusive access to HID""" 00081 assert self._locked 00082 00083 num = self._if .bInterfaceNumber 00084 usb.util.release_interface(self._dev , num) 00085 try: 00086 self._dev .attach_kernel_driver(num) 00087 except NotImplementedError: 00088 pass 00089 except usb.core.USBError: 00090 pass 00091 self._locked = False 00092 00093 def set_idle (self, report_id=0, duration=0): 00094 """Send a HID Set_Idle request""" 00095 assert self._locked 00096 assert report_id & ~0xFF == 0 00097 assert duration & ~0xFF == 0 00098 00099 request_type = 0x21 00100 request = 0x0A # SET_IDLE 00101 value = ((duration << 8) | (report_id << 0)) # Report and duration 00102 index = self._if .bInterfaceNumber # HID interface 00103 self._dev .ctrl_transfer(request_type, request, value, index, None) 00104 00105 def get_descriptor (self, desc_type, index): 00106 """Get the given descriptor""" 00107 assert self._locked 00108 assert desc_type & ~0xFF == 0 00109 assert index & ~0xFF == 0 00110 00111 request_type = 0x81 00112 request = 0x6 # GET_DESCRIPTOR 00113 value = (((index & 0xFF) << (0 * 8)) | 00114 ((desc_type & 0xFF) << (1 * 8))) # Descriptor type and index 00115 index = self._if .bInterfaceNumber # HID interface 00116 return self._dev .ctrl_transfer(request_type, request, 00117 value, index, 256) 00118 00119 def set_report_req (self, data, report_type=REPORT_TYPE_OUTPUT, 00120 report_id=0): 00121 """Set a report of the given type""" 00122 assert self._locked 00123 assert report_type & ~0xFF == 0 00124 assert report_id & ~0xFF == 0 00125 00126 request_type = 0x21 00127 request = 0x09 # SET_REPORT 00128 value = ((report_type << 8) | 00129 (report_id << 0)) # Report and duration 00130 index = self._if .bInterfaceNumber # HID interface 00131 self._dev .ctrl_transfer(request_type, request, value, index, data, 00132 self.timeout ) 00133 00134 def get_report_req (self, data_size, report_type=REPORT_TYPE_INPUT, 00135 report_id=0): 00136 """Set a report of the given type""" 00137 assert self._locked 00138 assert report_type & ~0xFF == 0 00139 assert report_id & ~0xFF == 0 00140 00141 request_type = 0xA1 00142 request = 0x01 # SET_REPORT 00143 value = ((report_type << 8) | 00144 (report_id << 0)) # Report and duration 00145 index = self._if .bInterfaceNumber # HID interface 00146 return self._dev .ctrl_transfer(request_type, request, value, index, 00147 data_size, self.timeout ) 00148 00149 def set_report (self, data): 00150 """Send report to the device""" 00151 assert self._locked 00152 00153 if self.ep_out is None: 00154 self.set_report_req (data) 00155 else: 00156 self.ep_out .write(data, 10 * 1000) 00157 00158 def get_report (self, size): 00159 """Read report from the device""" 00160 assert self._locked 00161 00162 return self.ep_in .read(size, 10 * 1000)
Generated on Tue Jul 12 2022 15:37:26 by
1.7.2