35 #if defined(PIOS_INCLUDE_USB_HID)
42 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
43 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
45 static void PIOS_USB_HID_RegisterTxCallback(uintptr_t usbhid_id,
pios_com_callback tx_out_cb, uintptr_t context);
46 static void PIOS_USB_HID_RegisterRxCallback(uintptr_t usbhid_id,
pios_com_callback rx_in_cb, uintptr_t context);
47 static void PIOS_USB_HID_TxStart(uintptr_t usbhid_id, uint16_t tx_bytes_avail);
48 static void PIOS_USB_HID_RxStart(uintptr_t usbhid_id, uint16_t rx_bytes_avail);
52 .rx_start = PIOS_USB_HID_RxStart,
53 .bind_tx_cb = PIOS_USB_HID_RegisterTxCallback,
54 .bind_rx_cb = PIOS_USB_HID_RegisterRxCallback,
58 enum pios_usb_hid_dev_magic {
59 PIOS_USB_HID_DEV_MAGIC = 0xAA00BB00,
62 struct pios_usb_hid_dev {
63 enum pios_usb_hid_dev_magic
magic;
69 uintptr_t rx_in_context;
71 uintptr_t tx_out_context;
85 static bool PIOS_USB_HID_validate(
struct pios_usb_hid_dev * usb_hid_dev)
87 return (usb_hid_dev && (usb_hid_dev->magic == PIOS_USB_HID_DEV_MAGIC));
90 static struct pios_usb_hid_dev * PIOS_USB_HID_alloc(
void)
92 struct pios_usb_hid_dev * usb_hid_dev;
94 usb_hid_dev = (
struct pios_usb_hid_dev *)
PIOS_malloc(
sizeof(*usb_hid_dev));
95 if (!usb_hid_dev)
return(NULL);
97 memset(usb_hid_dev, 0,
sizeof(*usb_hid_dev));
98 usb_hid_dev->magic = PIOS_USB_HID_DEV_MAGIC;
102 static void PIOS_USB_HID_IF_Init(uintptr_t usb_hid_id);
103 static void PIOS_USB_HID_IF_DeInit(uintptr_t usb_hid_id);
104 static bool PIOS_USB_HID_IF_Setup(uintptr_t usb_hid_id,
struct usb_setup_request *req);
105 static void PIOS_USB_HID_IF_CtrlDataOut(uintptr_t usb_hid_id,
const struct usb_setup_request *req);
108 .
init = PIOS_USB_HID_IF_Init,
109 .deinit = PIOS_USB_HID_IF_DeInit,
110 .setup = PIOS_USB_HID_IF_Setup,
111 .ctrl_data_out = PIOS_USB_HID_IF_CtrlDataOut,
114 static bool PIOS_USB_HID_EP_IN_Callback(uintptr_t usb_hid_id, uint8_t epnum, uint16_t len);
115 static bool PIOS_USB_HID_EP_OUT_Callback(uintptr_t usb_hid_id, uint8_t epnum, uint16_t len);
122 struct pios_usb_hid_dev * usb_hid_dev;
124 usb_hid_dev = (
struct pios_usb_hid_dev *) PIOS_USB_HID_alloc();
125 if (!usb_hid_dev)
goto out_fail;
128 usb_hid_dev->cfg =
cfg;
129 usb_hid_dev->lower_id = lower_id;
132 usb_hid_dev->rx_active =
false;
133 usb_hid_dev->tx_active =
false;
136 usb_hid_dev->usb_if_enabled =
false;
139 *usbhid_id = (uintptr_t) usb_hid_dev;
152 hid_desc.descriptor =
desc;
164 static bool PIOS_USB_HID_SendReport(
struct pios_usb_hid_dev * usb_hid_dev)
166 uint16_t bytes_to_tx;
168 if (!usb_hid_dev->tx_out_cb) {
172 bool need_yield =
false;
173 #ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
174 bytes_to_tx = (usb_hid_dev->tx_out_cb)(usb_hid_dev->tx_out_context,
175 &usb_hid_dev->tx_packet_buffer[1],
176 sizeof(usb_hid_dev->tx_packet_buffer)-1,
180 bytes_to_tx = (usb_hid_dev->tx_out_cb)(usb_hid_dev->tx_out_context,
181 &usb_hid_dev->tx_packet_buffer[2],
182 sizeof(usb_hid_dev->tx_packet_buffer)-2,
186 if (bytes_to_tx == 0) {
194 usb_hid_dev->tx_active =
true;
197 usb_hid_dev->tx_packet_buffer[0] = 1;
199 #ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
201 usb_hid_dev->tx_packet_buffer,
202 sizeof(usb_hid_dev->tx_packet_buffer));
204 usb_hid_dev->tx_packet_buffer[1] = bytes_to_tx;
206 usb_hid_dev->tx_packet_buffer,
207 sizeof(usb_hid_dev->tx_packet_buffer));
213 static void PIOS_USB_HID_RxStart(uintptr_t usbhid_id, uint16_t rx_bytes_avail) {
214 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usbhid_id;
216 bool valid = PIOS_USB_HID_validate(usb_hid_dev);
220 if (!usb_hid_dev->usb_if_enabled) {
229 #ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
235 if (!usb_hid_dev->rx_active && (rx_bytes_avail >= max_payload_length)) {
237 usb_hid_dev->rx_packet_buffer,
238 sizeof(usb_hid_dev->rx_packet_buffer));
239 usb_hid_dev->rx_active =
true;
243 static void PIOS_USB_HID_TxStart(uintptr_t usbhid_id, uint16_t tx_bytes_avail)
245 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usbhid_id;
247 bool valid = PIOS_USB_HID_validate(usb_hid_dev);
251 if (!usb_hid_dev->usb_if_enabled) {
259 if (!usb_hid_dev->tx_active) {
261 PIOS_USB_HID_SendReport(usb_hid_dev);
265 static void PIOS_USB_HID_RegisterRxCallback(uintptr_t usbhid_id,
pios_com_callback rx_in_cb, uintptr_t context)
267 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usbhid_id;
269 bool valid = PIOS_USB_HID_validate(usb_hid_dev);
276 usb_hid_dev->rx_in_context = context;
277 usb_hid_dev->rx_in_cb = rx_in_cb;
280 static void PIOS_USB_HID_RegisterTxCallback(uintptr_t usbhid_id,
pios_com_callback tx_out_cb, uintptr_t context)
282 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usbhid_id;
284 bool valid = PIOS_USB_HID_validate(usb_hid_dev);
291 usb_hid_dev->tx_out_context = context;
292 usb_hid_dev->tx_out_cb = tx_out_cb;
295 static void PIOS_USB_HID_IF_Init(uintptr_t usb_hid_id)
297 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usb_hid_id;
299 if (!PIOS_USB_HID_validate(usb_hid_dev)) {
305 sizeof(usb_hid_dev->tx_packet_buffer),
306 PIOS_USB_HID_EP_IN_Callback,
307 (uintptr_t) usb_hid_dev);
309 sizeof(usb_hid_dev->rx_packet_buffer),
310 PIOS_USB_HID_EP_OUT_Callback,
311 (uintptr_t) usb_hid_dev);
312 usb_hid_dev->usb_if_enabled =
true;
316 static void PIOS_USB_HID_IF_DeInit(uintptr_t usb_hid_id)
318 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usb_hid_id;
320 if (!PIOS_USB_HID_validate(usb_hid_dev)) {
325 usb_hid_dev->rx_active =
false;
326 usb_hid_dev->rx_dropped = 0;
327 usb_hid_dev->rx_oversize = 0;
328 usb_hid_dev->tx_active =
false;
329 usb_hid_dev->usb_if_enabled =
false;
336 static uint8_t hid_protocol;
337 static uint8_t hid_altset;
339 struct hid_idle_msg {
343 static struct hid_idle_msg hid_idle;
344 static uint8_t dummy_report[2];
346 static bool PIOS_USB_HID_IF_Setup(uintptr_t usb_hid_id,
struct usb_setup_request *req)
348 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usb_hid_id;
350 if (!PIOS_USB_HID_validate(usb_hid_dev)) {
355 uint8_t ifnum = req->
wIndex & 0xFF;
356 if (ifnum != usb_hid_dev->cfg->data_if) {
364 switch (req->
wValue >> 8) {
383 hid_altset = (uint8_t)(req->
wValue);
394 hid_protocol = (uint8_t)(req->
wValue);
398 hid_idle.idle_period = req->
wValue & 0xFF00 >> 8;
399 hid_idle.report_id = req->
wValue & 0x00FF;
406 dummy_report[0] = req->
wValue & 0xFF;
407 dummy_report[1] = 0x00;
425 static void PIOS_USB_HID_IF_CtrlDataOut(uintptr_t usb_hid_id,
const struct usb_setup_request *req)
435 static bool PIOS_USB_HID_EP_IN_Callback(uintptr_t usb_hid_id, uint8_t epnum, uint16_t len)
437 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usb_hid_id;
439 if (!PIOS_USB_HID_validate(usb_hid_dev)) {
444 PIOS_USB_HID_SendReport(usb_hid_dev)) {
449 usb_hid_dev->tx_active =
false;
457 static bool PIOS_USB_HID_EP_OUT_Callback(uintptr_t usb_hid_id, uint8_t epnum, uint16_t len)
459 struct pios_usb_hid_dev * usb_hid_dev = (
struct pios_usb_hid_dev *)usb_hid_id;
461 if (!PIOS_USB_HID_validate(usb_hid_dev)) {
465 if (len >
sizeof(usb_hid_dev->rx_packet_buffer)) {
466 len =
sizeof(usb_hid_dev->rx_packet_buffer);
469 if (!usb_hid_dev->rx_in_cb) {
471 usb_hid_dev->rx_active =
false;
477 bool need_yield =
false;
478 #ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
479 (usb_hid_dev->rx_in_cb)(usb_hid_dev->rx_in_context,
480 &usb_hid_dev->rx_packet_buffer[1],
485 (usb_hid_dev->rx_in_cb)(usb_hid_dev->rx_in_context,
486 &usb_hid_dev->rx_packet_buffer[2],
487 usb_hid_dev->rx_packet_buffer[1],
492 #ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
499 if (headroom >= max_payload_length) {
502 usb_hid_dev->rx_packet_buffer,
503 sizeof(usb_hid_dev->rx_packet_buffer));
507 usb_hid_dev->rx_active =
false;
void PIOS_USBHOOK_CtrlTx(const uint8_t *buf, uint16_t len)
Main PiOS header to include all the compiled in PiOS options.
#define USB_REQ_TYPE_CLASS
APIs for PIOS_USBHOOK layer.
static const uint8_t hid_report_desc[]
#define USB_REQ_TYPE_MASK
#define USB_REQ_TYPE_STANDARD
void * PIOS_malloc(size_t size)
bool PIOS_USB_CheckAvailable(uintptr_t id)
int32_t PIOS_USB_HID_Init(uintptr_t *usbhid_id, const struct pios_usb_hid_cfg *cfg, uintptr_t lower_id)
#define USB_REQ_RECIPIENT_MASK
void(* init)(uintptr_t context)
static struct flyingpicmd_cfg_fa cfg
const struct pios_com_driver pios_usb_hid_com_driver
void PIOS_USBHOOK_EndpointRx(uint8_t epnum, uint8_t *buf, uint16_t len)
#define USB_REQ_RECIPIENT_INTERFACE
void PIOS_USBHOOK_RegisterEpInCallback(uint8_t epnum, uint16_t max_len, pios_usbhook_epcb cb, uintptr_t context)
USB HID layer functions header.
USB COM HID private definitions.
#define PIOS_USB_BOARD_HID_DATA_LENGTH
void PIOS_USB_HID_RegisterHidReport(const uint8_t *desc, uint16_t length)
void PIOS_USBHOOK_EndpointTx(uint8_t epnum, const uint8_t *buf, uint16_t len)
void PIOS_USBHOOK_DeRegisterEpInCallback(uint8_t epnum)
void PIOS_USBHOOK_RegisterEpOutCallback(uint8_t epnum, uint16_t max_len, pios_usbhook_epcb cb, uintptr_t context)
void PIOS_USB_HID_RegisterHidDescriptor(const uint8_t *desc, uint16_t length)
void PIOS_USBHOOK_DeRegisterEpOutCallback(uint8_t epnum)
#define PIOS_Assert(test)
void(* tx_start)(uintptr_t id, uint16_t tx_bytes_avail)
void PIOS_USBHOOK_RegisterIfOps(uint8_t ifnum, struct pios_usb_ifops *ifops, uintptr_t context)
uint16_t(* pios_com_callback)(uintptr_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, bool *task_woken)