Пример #1
0
static void PIOS_USB_HID_RxStart(uint32_t usbhid_id, uint16_t rx_bytes_avail) {
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usbhid_id;

	bool valid = PIOS_USB_HID_validate(usb_hid_dev);
	PIOS_Assert(valid);

	/* Make sure this USB interface has been initialized */
	if (!usb_hid_dev->usb_if_enabled) {
		return;
	}

	if (!PIOS_USB_CheckAvailable(usb_hid_dev->lower_id)) {
		return;
	}

	// If endpoint was stalled and there is now space make it valid
#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
	uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 1;
#else
	uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 2;
#endif

	if (!usb_hid_dev->rx_active && (rx_bytes_avail >= max_payload_length)) {
		PIOS_USBHOOK_EndpointRx(usb_hid_dev->cfg->data_rx_ep,
					usb_hid_dev->rx_packet_buffer,
					sizeof(usb_hid_dev->rx_packet_buffer));
		usb_hid_dev->rx_active = true;
	}
}
Пример #2
0
/**
 * @brief Callback used to indicate a transmission from device INto host completed
 * Checks if any data remains, pads it into HID packet and sends.
 */
static void PIOS_USB_HID_EP_IN_Callback(void)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)pios_usb_hid_id;

	bool valid = PIOS_USB_HID_validate(usb_hid_dev);
	PIOS_Assert(valid);

	if (!PIOS_USB_CheckAvailable(usb_hid_dev->lower_id)) {
		return;
	}

	PIOS_USB_HID_SendReport(usb_hid_dev);
}
Пример #3
0
static void PIOS_USB_HID_IF_DeInit(uint32_t usb_hid_id)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usb_hid_id;

	if (!PIOS_USB_HID_validate(usb_hid_dev)) {
		return;
	}

	/* DeRegister endpoint specific callbacks with the USBHOOK layer */
	usb_hid_dev->usb_if_enabled = false;
	PIOS_USBHOOK_DeRegisterEpInCallback(usb_hid_dev->cfg->data_tx_ep);
	PIOS_USBHOOK_DeRegisterEpOutCallback(usb_hid_dev->cfg->data_rx_ep);
}
Пример #4
0
static void PIOS_USB_HID_RegisterTxCallback(uint32_t usbhid_id, pios_com_callback tx_out_cb, uint32_t context)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usbhid_id;

	bool valid = PIOS_USB_HID_validate(usb_hid_dev);
	PIOS_Assert(valid);

	/* 
	 * Order is important in these assignments since ISR uses _cb
	 * field to determine if it's ok to dereference _cb and _context
	 */
	usb_hid_dev->tx_out_context = context;
	usb_hid_dev->tx_out_cb = tx_out_cb;
}
Пример #5
0
static void PIOS_USB_HID_TxStart(uint32_t usbhid_id, uint16_t tx_bytes_avail)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usbhid_id;

	bool valid = PIOS_USB_HID_validate(usb_hid_dev);
	PIOS_Assert(valid);

	if (!PIOS_USB_CheckAvailable(usb_hid_dev->lower_id)) {
		return;
	}

	if (GetEPTxStatus(usb_hid_dev->cfg->data_tx_ep) == EP_TX_VALID) {
		/* Endpoint is already transmitting */
		return;
	}

	PIOS_USB_HID_SendReport(usb_hid_dev);
}
Пример #6
0
/**
 * @brief Callback used to indicate a transmission from device INto host completed
 * Checks if any data remains, pads it into HID packet and sends.
 */
static bool PIOS_USB_HID_EP_IN_Callback(uint32_t usb_hid_id, uint8_t epnum, uint16_t len)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usb_hid_id;

	if (!PIOS_USB_HID_validate(usb_hid_dev)) {
		return false;
	}

	if (PIOS_USB_CheckAvailable(usb_hid_dev->lower_id) &&
		PIOS_USB_HID_SendReport(usb_hid_dev)) {
		/* More data has been queued, leave tx_active set to true */
		return true;
	} else {
		/* Nothing new sent, transmitter is now inactive */
		usb_hid_dev->tx_active = false;
		return false;
	}
}
Пример #7
0
static void PIOS_USB_HID_IF_DeInit(uintptr_t usb_hid_id)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usb_hid_id;

	if (!PIOS_USB_HID_validate(usb_hid_dev)) {
		return;
	}

	/* reset state of the usb hid device structure */
	usb_hid_dev->rx_active = false;
	usb_hid_dev->rx_dropped = 0;
	usb_hid_dev->rx_oversize = 0;
	usb_hid_dev->tx_active = false;
	usb_hid_dev->usb_if_enabled = false;

	/* DeRegister endpoint specific callbacks with the USBHOOK layer */
	PIOS_USBHOOK_DeRegisterEpInCallback(usb_hid_dev->cfg->data_tx_ep);
	PIOS_USBHOOK_DeRegisterEpOutCallback(usb_hid_dev->cfg->data_rx_ep);
}
Пример #8
0
static void PIOS_USB_HID_IF_Init(uint32_t usb_hid_id)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usb_hid_id;

	if (!PIOS_USB_HID_validate(usb_hid_dev)) {
		return;
	}

	/* Register endpoint specific callbacks with the USBHOOK layer */
	PIOS_USBHOOK_RegisterEpInCallback(usb_hid_dev->cfg->data_tx_ep,
					  sizeof(usb_hid_dev->tx_packet_buffer),
					  PIOS_USB_HID_EP_IN_Callback,
					  (uint32_t) usb_hid_dev);
	PIOS_USBHOOK_RegisterEpOutCallback(usb_hid_dev->cfg->data_rx_ep,
					   sizeof(usb_hid_dev->rx_packet_buffer),
					   PIOS_USB_HID_EP_OUT_Callback,
					   (uint32_t) usb_hid_dev);
	usb_hid_dev->usb_if_enabled = true;

}
Пример #9
0
static void PIOS_USB_HID_TxStart(uint32_t usbhid_id, uint16_t tx_bytes_avail)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usbhid_id;

	bool valid = PIOS_USB_HID_validate(usb_hid_dev);
	PIOS_Assert(valid);

	/* Make sure this USB interface has been initialized */
	if (!usb_hid_dev->usb_if_enabled) {
		return;
	}

	if (!PIOS_USB_CheckAvailable(usb_hid_dev->lower_id)) {
		return;
	}

	if (!usb_hid_dev->tx_active) {
		/* Transmitter is not currently active, send a report */
		PIOS_USB_HID_SendReport(usb_hid_dev);
	}
}
Пример #10
0
static void PIOS_USB_HID_RxStart(uint32_t usbhid_id, uint16_t rx_bytes_avail) {
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usbhid_id;

	bool valid = PIOS_USB_HID_validate(usb_hid_dev);
	PIOS_Assert(valid);

	if (!PIOS_USB_CheckAvailable(usb_hid_dev->lower_id)) {
		return;
	}

	// If endpoint was stalled and there is now space make it valid
#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
	uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 1;
#else
	uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 2;
#endif

	PIOS_IRQ_Disable();
	if ((GetEPRxStatus(usb_hid_dev->cfg->data_rx_ep) != EP_RX_VALID) && 
	    (rx_bytes_avail >= max_payload_length)) {
		SetEPRxStatus(usb_hid_dev->cfg->data_rx_ep, EP_RX_VALID);
	}
	PIOS_IRQ_Enable();
}
Пример #11
0
/**
 * EP1 OUT Callback Routine
 */
static void PIOS_USB_HID_EP_OUT_Callback(void)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)pios_usb_hid_id;

	bool valid = PIOS_USB_HID_validate(usb_hid_dev);
	PIOS_Assert(valid);

	uint32_t DataLength;

	/* Read received data (63 bytes) */
	/* Get the number of received data on the selected Endpoint */
	DataLength = GetEPRxCount(usb_hid_dev->cfg->data_rx_ep);
	if (DataLength > sizeof(usb_hid_dev->rx_packet_buffer)) {
		DataLength = sizeof(usb_hid_dev->rx_packet_buffer);
	}

	/* Use the memory interface function to read from the selected endpoint */
	PMAToUserBufferCopy((uint8_t *) usb_hid_dev->rx_packet_buffer,
			GetEPRxAddr(usb_hid_dev->cfg->data_rx_ep),
			DataLength);

	if (!usb_hid_dev->rx_in_cb) {
		/* No Rx call back registered, disable the receiver */
		SetEPRxStatus(usb_hid_dev->cfg->data_rx_ep, EP_RX_NAK);
		return;
	}

	/* The first byte is report ID (not checked), the second byte is the valid data length */
	uint16_t headroom;
	bool need_yield = false;
#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
	(usb_hid_dev->rx_in_cb)(usb_hid_dev->rx_in_context,
				&usb_hid_dev->rx_packet_buffer[1],
				sizeof(usb_hid_dev->rx_packet_buffer)-1,
				&headroom,
				&need_yield);
#else
	(usb_hid_dev->rx_in_cb)(usb_hid_dev->rx_in_context,
				&usb_hid_dev->rx_packet_buffer[2],
				usb_hid_dev->rx_packet_buffer[1],
				&headroom,
				&need_yield);
#endif

#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
	uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 1;
#else
	uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 2;
#endif

	if (headroom >= max_payload_length) {

		/* We have room for a maximum length message */
		SetEPRxStatus(usb_hid_dev->cfg->data_rx_ep, EP_RX_VALID);
	} else {
		/* Not enough room left for a message, apply backpressure */
		SetEPRxStatus(usb_hid_dev->cfg->data_rx_ep, EP_RX_NAK);
	}

#if defined(PIOS_INCLUDE_FREERTOS)
	if (need_yield) {
		vPortYieldFromISR();
	}
#endif	/* PIOS_INCLUDE_FREERTOS */
}
Пример #12
0
/**
 * EP1 OUT Callback Routine
 */
static bool PIOS_USB_HID_EP_OUT_Callback(uint32_t usb_hid_id, uint8_t epnum, uint16_t len)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usb_hid_id;

	if (!PIOS_USB_HID_validate(usb_hid_dev)) {
		return false;
	}

	if (len > sizeof(usb_hid_dev->rx_packet_buffer)) {
		len = sizeof(usb_hid_dev->rx_packet_buffer);
	}

	if (!usb_hid_dev->rx_in_cb) {
		/* No Rx call back registered, disable the receiver */
		usb_hid_dev->rx_active = false;
		return false;
	}

	/* The first byte is report ID (not checked), the second byte is the valid data length */
	uint16_t headroom;
	bool need_yield = false;
#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
	(usb_hid_dev->rx_in_cb)(usb_hid_dev->rx_in_context,
				&usb_hid_dev->rx_packet_buffer[1],
				len-1,
				&headroom,
				&need_yield);
#else
	(usb_hid_dev->rx_in_cb)(usb_hid_dev->rx_in_context,
				&usb_hid_dev->rx_packet_buffer[2],
				usb_hid_dev->rx_packet_buffer[1],
				&headroom,
				&need_yield);
#endif

#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE
	uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 1;
#else
	uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 2;
#endif

	bool rc;
	if (headroom >= max_payload_length) {
		/* We have room for a maximum length message */
		PIOS_USBHOOK_EndpointRx(usb_hid_dev->cfg->data_rx_ep,
					usb_hid_dev->rx_packet_buffer,
					sizeof(usb_hid_dev->rx_packet_buffer));
		rc = true;
	} else {
		/* Not enough room left for a message, apply backpressure */
		usb_hid_dev->rx_active = false;
		rc = false;
	}

#if defined(PIOS_INCLUDE_FREERTOS)
	if (need_yield) {
		vPortYieldFromISR();
	}
#endif	/* PIOS_INCLUDE_FREERTOS */

	return rc;
}
Пример #13
0
static bool PIOS_USB_HID_IF_Setup(uint32_t usb_hid_id, struct usb_setup_request *req)
{
	struct pios_usb_hid_dev * usb_hid_dev = (struct pios_usb_hid_dev *)usb_hid_id;

	if (!PIOS_USB_HID_validate(usb_hid_dev)) {
		return false;
	}

	/* Make sure this is a request for an interface we know about */
	uint8_t ifnum = req->wIndex & 0xFF;
	if (ifnum != usb_hid_dev->cfg->data_if) {
		return (false);
	}

	switch (req->bmRequestType & (USB_REQ_TYPE_MASK | USB_REQ_RECIPIENT_MASK)) {
	case (USB_REQ_TYPE_STANDARD | USB_REQ_RECIPIENT_INTERFACE):
		switch (req->bRequest) {
		case USB_REQ_GET_DESCRIPTOR:
			switch (req->wValue >> 8) {
			case USB_DESC_TYPE_REPORT:
				PIOS_USBHOOK_CtrlTx(hid_report_desc.descriptor,
						MIN(hid_report_desc.length, req->wLength));
				break;
			case USB_DESC_TYPE_HID:
				PIOS_USBHOOK_CtrlTx(hid_desc.descriptor,
						MIN(hid_desc.length, req->wLength));
				break;
			default:
				/* Unhandled descriptor request */
				return false;
				break;
			}
			break;
		case USB_REQ_GET_INTERFACE:
			PIOS_USBHOOK_CtrlTx(&hid_altset, 1);
			break;
		case USB_REQ_SET_INTERFACE:
			hid_altset = (uint8_t)(req->wValue);
			break;
		default:
			/* Unhandled standard request */
			return false;
			break;
		}
		break;
	case (USB_REQ_TYPE_CLASS    | USB_REQ_RECIPIENT_INTERFACE):
		switch (req->bRequest) {
		case USB_HID_REQ_SET_PROTOCOL:
			hid_protocol = (uint8_t)(req->wValue);
			break;
		case USB_HID_REQ_GET_PROTOCOL:
			PIOS_USBHOOK_CtrlTx(&hid_protocol, 1);
			break;
		case USB_HID_REQ_GET_REPORT:
		{
			/* Give back a dummy input report */
			uint8_t dummy_report[2] = {
				[0]     = req->wValue >> 8, /* Report ID */
				[1]     = 0x00,
			};
			PIOS_USBHOOK_CtrlTx(dummy_report, sizeof(dummy_report));
		}
		break;
		default:
			/* Unhandled class request */
			return false;
			break;
		}
		break;
	default:
		/* Unhandled request */
		return false;
	}

	return true;
}

static void PIOS_USB_HID_IF_CtrlDataOut(uint32_t usb_hid_id, struct usb_setup_request *req)
{
	/* HID devices don't have any OUT data stages on the control endpoint */
	PIOS_Assert(0);
}