fa07deda9f
The previous version did not work on MCUs that only had USB device mode (compared to OTG) because of the handling of NAK. And this previous handling of NAK had a race condition where a new packet could come in before USBD_HID_SetNAK was called (since USBD_HID_ReceivePacket clears NAK as part of its operation). Furthermore, the double buffering of incoming reports was not working, only one buffer could be used at a time. This commit rewrites the HID interface code to have a single incoming buffer, and only calls USBD_HID_ReceivePacket after the user has read the incoming report (similar to how the VCP does its flow control). As such, USBD_HID_SetNAK and USBD_HID_ClearNAK are no longer needed. API functionality from the user's point of view should be unchanged with this commit.
71 lines
2.6 KiB
C
71 lines
2.6 KiB
C
/*
|
|
* This file is part of the MicroPython project, http://micropython.org/
|
|
*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2019 Damien P. George
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
#include "usbd_hid_interface.h"
|
|
|
|
#include "py/mperrno.h"
|
|
#include "py/mphal.h"
|
|
#include "usb.h"
|
|
|
|
#if MICROPY_HW_USB_HID
|
|
|
|
uint8_t *usbd_hid_init(usbd_hid_state_t *hid_in) {
|
|
usbd_hid_itf_t *hid = (usbd_hid_itf_t*)hid_in;
|
|
hid->report_in_len = USBD_HID_REPORT_INVALID;
|
|
return &hid->report_in_buf[0]; // location to place first incoming report
|
|
}
|
|
|
|
int8_t usbd_hid_receive(usbd_hid_state_t *hid_in, size_t len) {
|
|
// Incoming report: save the length but don't schedule next report until user reads this one
|
|
usbd_hid_itf_t *hid = (usbd_hid_itf_t*)hid_in;
|
|
hid->report_in_len = len;
|
|
return USBD_OK;
|
|
}
|
|
|
|
int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_ms) {
|
|
// Wait for an incoming report
|
|
uint32_t t0 = mp_hal_ticks_ms();
|
|
while (hid->report_in_len == USBD_HID_REPORT_INVALID) {
|
|
if (mp_hal_ticks_ms() - t0 >= timeout_ms || query_irq() == IRQ_STATE_DISABLED) {
|
|
return -MP_ETIMEDOUT;
|
|
}
|
|
MICROPY_EVENT_POLL_HOOK
|
|
}
|
|
|
|
// Copy bytes from report to user buffer
|
|
int n = MIN(len, hid->report_in_len);
|
|
memcpy(buf, &hid->report_in_buf[0], n);
|
|
|
|
// Schedule to receive next incoming report
|
|
hid->report_in_len = USBD_HID_REPORT_INVALID;
|
|
USBD_HID_ReceivePacket(&hid->base, &hid->report_in_buf[0]);
|
|
|
|
// Return number of bytes read into user buffer
|
|
return n;
|
|
}
|
|
|
|
#endif // MICROPY_HW_USB_HID
|