Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
Diff: test/usb_hid.py
- Revision:
- 0:01f31e923fe2
diff -r 000000000000 -r 01f31e923fe2 test/usb_hid.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/usb_hid.py Tue Apr 07 12:55:42 2020 +0200 @@ -0,0 +1,162 @@ +# +# DAPLink Interface Firmware +# Copyright (c) 2016-2016, ARM Limited, All Rights Reserved +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import usb.util + + +class USBHid(object): + """Wrapper class for a HID usb device""" + + # HID commands documented in + # Device Class Definition for Human Interface Devices (HID) + + CLASS_HID = 0x3 + + DESC_TYPE_HID = 0x21 + DESC_TYPE_REPORT = 0x22 + DESC_TYPE_PHYSICAL = 0x23 + + REPORT_TYPE_INPUT = 1 + REPORT_TYPE_OUTPUT = 2 + REPORT_TYPE_FEATURE = 3 + + def __init__(self, device): + self._dev = device + self._if = None + self.ep_in = None + self.ep_out = None + self._locked = False + self.timeout = 10 * 1000 + + # Find interface + for interface in device.get_active_configuration(): + if interface.bInterfaceClass == USBHid.CLASS_HID: + assert self._if is None + self._if = interface + assert self._if is not None + + # Find endpoints + for endpoint in self._if: + if endpoint.bEndpointAddress & 0x80: + assert self.ep_in is None + self.ep_in = endpoint + else: + assert self.ep_out is None + self.ep_out = endpoint + assert self.ep_in is not None + # Endpoint out can be None + + def lock(self): + """Acquire exclisive access to HID""" + assert not self._locked + + num = self._if.bInterfaceNumber + try: + if self._dev.is_kernel_driver_active(num): + self._dev.detach_kernel_driver(num) + except NotImplementedError: + pass + except usb.core.USBError: + pass + usb.util.claim_interface(self._dev, num) + self._locked = True + + def unlock(self): + """Release exclusive access to HID""" + assert self._locked + + num = self._if.bInterfaceNumber + usb.util.release_interface(self._dev, num) + try: + self._dev.attach_kernel_driver(num) + except NotImplementedError: + pass + except usb.core.USBError: + pass + self._locked = False + + def set_idle(self, report_id=0, duration=0): + """Send a HID Set_Idle request""" + assert self._locked + assert report_id & ~0xFF == 0 + assert duration & ~0xFF == 0 + + request_type = 0x21 + request = 0x0A # SET_IDLE + value = ((duration << 8) | (report_id << 0)) # Report and duration + index = self._if.bInterfaceNumber # HID interface + self._dev.ctrl_transfer(request_type, request, value, index, None) + + def get_descriptor(self, desc_type, index): + """Get the given descriptor""" + assert self._locked + assert desc_type & ~0xFF == 0 + assert index & ~0xFF == 0 + + request_type = 0x81 + request = 0x6 # GET_DESCRIPTOR + value = (((index & 0xFF) << (0 * 8)) | + ((desc_type & 0xFF) << (1 * 8))) # Descriptor type and index + index = self._if.bInterfaceNumber # HID interface + return self._dev.ctrl_transfer(request_type, request, + value, index, 256) + + def set_report_req(self, data, report_type=REPORT_TYPE_OUTPUT, + report_id=0): + """Set a report of the given type""" + assert self._locked + assert report_type & ~0xFF == 0 + assert report_id & ~0xFF == 0 + + request_type = 0x21 + request = 0x09 # SET_REPORT + value = ((report_type << 8) | + (report_id << 0)) # Report and duration + index = self._if.bInterfaceNumber # HID interface + self._dev.ctrl_transfer(request_type, request, value, index, data, + self.timeout) + + def get_report_req(self, data_size, report_type=REPORT_TYPE_INPUT, + report_id=0): + """Set a report of the given type""" + assert self._locked + assert report_type & ~0xFF == 0 + assert report_id & ~0xFF == 0 + + request_type = 0xA1 + request = 0x01 # SET_REPORT + value = ((report_type << 8) | + (report_id << 0)) # Report and duration + index = self._if.bInterfaceNumber # HID interface + return self._dev.ctrl_transfer(request_type, request, value, index, + data_size, self.timeout) + + def set_report(self, data): + """Send report to the device""" + assert self._locked + + if self.ep_out is None: + self.set_report_req(data) + else: + self.ep_out.write(data, 10 * 1000) + + def get_report(self, size): + """Read report from the device""" + assert self._locked + + return self.ep_in.read(size, 10 * 1000)