Merge remote-tracking branch 'remotes/tinyusb/master' into rx_fb
This commit is contained in:
@@ -39,12 +39,11 @@
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF
|
||||
//--------------------------------------------------------------------+
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint8_t itf_num;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out; // optional Out endpoint
|
||||
uint8_t itf_protocol; // Boot mouse or keyboard
|
||||
uint8_t ep_out; // optional Out endpoint
|
||||
uint8_t itf_protocol; // Boot mouse or keyboard
|
||||
|
||||
uint16_t report_desc_len;
|
||||
CFG_TUSB_MEM_ALIGN uint8_t protocol_mode; // Boot (0) or Report protocol (1)
|
||||
@@ -56,7 +55,7 @@ typedef struct
|
||||
|
||||
// TODO save hid descriptor since host can specifically request this after enumeration
|
||||
// Note: HID descriptor may be not available from application after enumeration
|
||||
tusb_hid_descriptor_hid_t const * hid_descriptor;
|
||||
tusb_hid_descriptor_hid_t const *hid_descriptor;
|
||||
} hidd_interface_t;
|
||||
|
||||
CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID];
|
||||
@@ -64,12 +63,12 @@ CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID];
|
||||
/*------------- Helpers -------------*/
|
||||
static inline uint8_t get_index_by_itfnum(uint8_t itf_num)
|
||||
{
|
||||
for (uint8_t i=0; i < CFG_TUD_HID; i++ )
|
||||
{
|
||||
if ( itf_num == _hidd_itf[i].itf_num ) return i;
|
||||
}
|
||||
for (uint8_t i = 0; i < CFG_TUD_HID; i++) {
|
||||
if (itf_num == _hidd_itf[i].itf_num)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -82,37 +81,29 @@ bool tud_hid_n_ready(uint8_t instance)
|
||||
return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(rhport, ep_in);
|
||||
}
|
||||
|
||||
bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, uint16_t len)
|
||||
bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, uint16_t len)
|
||||
{
|
||||
uint8_t const rhport = 0;
|
||||
hidd_interface_t * p_hid = &_hidd_itf[instance];
|
||||
hidd_interface_t *p_hid = &_hidd_itf[instance];
|
||||
|
||||
// claim endpoint
|
||||
TU_VERIFY( usbd_edpt_claim(rhport, p_hid->ep_in) );
|
||||
TU_VERIFY(usbd_edpt_claim(rhport, p_hid->ep_in));
|
||||
|
||||
// prepare data
|
||||
if (report_id)
|
||||
{
|
||||
if (report_id) {
|
||||
p_hid->epin_buf[0] = report_id;
|
||||
TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf+1, CFG_TUD_HID_EP_BUFSIZE-1, report, len));
|
||||
TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf + 1, CFG_TUD_HID_EP_BUFSIZE - 1, report, len));
|
||||
len++;
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf, CFG_TUD_HID_EP_BUFSIZE, report, len));
|
||||
}
|
||||
|
||||
return usbd_edpt_xfer(rhport, p_hid->ep_in, p_hid->epin_buf, len);
|
||||
}
|
||||
|
||||
uint8_t tud_hid_n_interface_protocol(uint8_t instance)
|
||||
{
|
||||
return _hidd_itf[instance].itf_protocol;
|
||||
}
|
||||
uint8_t tud_hid_n_interface_protocol(uint8_t instance) { return _hidd_itf[instance].itf_protocol; }
|
||||
|
||||
uint8_t tud_hid_n_get_protocol(uint8_t instance)
|
||||
{
|
||||
return _hidd_itf[instance].protocol_mode;
|
||||
}
|
||||
uint8_t tud_hid_n_get_protocol(uint8_t instance) { return _hidd_itf[instance].protocol_mode; }
|
||||
|
||||
bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6])
|
||||
{
|
||||
@@ -121,27 +112,23 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi
|
||||
report.modifier = modifier;
|
||||
report.reserved = 0;
|
||||
|
||||
if ( keycode )
|
||||
{
|
||||
if (keycode) {
|
||||
memcpy(report.keycode, keycode, sizeof(report.keycode));
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
tu_memclr(report.keycode, 6);
|
||||
}
|
||||
|
||||
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
|
||||
}
|
||||
|
||||
bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id,
|
||||
uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
|
||||
bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
|
||||
{
|
||||
hid_mouse_report_t report =
|
||||
{
|
||||
hid_mouse_report_t report = {
|
||||
.buttons = buttons,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.wheel = vertical,
|
||||
.pan = horizontal
|
||||
.x = x,
|
||||
.y = y,
|
||||
.wheel = vertical,
|
||||
.pan = horizontal
|
||||
};
|
||||
|
||||
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
|
||||
@@ -149,29 +136,27 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id,
|
||||
|
||||
bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal)
|
||||
{
|
||||
hid_abs_mouse_report_t report =
|
||||
{
|
||||
hid_abs_mouse_report_t report = {
|
||||
.buttons = buttons,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.wheel = vertical,
|
||||
.pan = horizontal
|
||||
.x = x,
|
||||
.y = y,
|
||||
.wheel = vertical,
|
||||
.pan = horizontal
|
||||
};
|
||||
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
|
||||
}
|
||||
|
||||
bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id,
|
||||
int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) {
|
||||
hid_gamepad_report_t report =
|
||||
{
|
||||
.x = x,
|
||||
.y = y,
|
||||
.z = z,
|
||||
.rz = rz,
|
||||
.rx = rx,
|
||||
.ry = ry,
|
||||
.hat = hat,
|
||||
.buttons = buttons,
|
||||
bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons)
|
||||
{
|
||||
hid_gamepad_report_t report = {
|
||||
.x = x,
|
||||
.y = y,
|
||||
.z = z,
|
||||
.rz = rz,
|
||||
.rx = rx,
|
||||
.ry = ry,
|
||||
.hat = hat,
|
||||
.buttons = buttons,
|
||||
};
|
||||
|
||||
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
|
||||
@@ -180,67 +165,64 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id,
|
||||
//--------------------------------------------------------------------+
|
||||
// USBD-CLASS API
|
||||
//--------------------------------------------------------------------+
|
||||
void hidd_init(void) {
|
||||
void hidd_init(void)
|
||||
{
|
||||
hidd_reset(0);
|
||||
}
|
||||
|
||||
bool hidd_deinit(void) {
|
||||
bool hidd_deinit(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void hidd_reset(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
(void)rhport;
|
||||
tu_memclr(_hidd_itf, sizeof(_hidd_itf));
|
||||
}
|
||||
|
||||
uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len)
|
||||
{
|
||||
uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
|
||||
{
|
||||
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0);
|
||||
|
||||
// len = interface + hid + n*endpoints
|
||||
uint16_t const drv_len =
|
||||
(uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) +
|
||||
desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
|
||||
uint16_t const drv_len = (uint16_t)(sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
|
||||
TU_ASSERT(max_len >= drv_len, 0);
|
||||
|
||||
// Find available interface
|
||||
hidd_interface_t * p_hid = NULL;
|
||||
hidd_interface_t *p_hid = NULL;
|
||||
uint8_t hid_id;
|
||||
for(hid_id=0; hid_id<CFG_TUD_HID; hid_id++)
|
||||
{
|
||||
if ( _hidd_itf[hid_id].ep_in == 0 )
|
||||
{
|
||||
for (hid_id = 0; hid_id < CFG_TUD_HID; hid_id++) {
|
||||
if (_hidd_itf[hid_id].ep_in == 0) {
|
||||
p_hid = &_hidd_itf[hid_id];
|
||||
break;
|
||||
}
|
||||
}
|
||||
TU_ASSERT(p_hid, 0);
|
||||
|
||||
uint8_t const *p_desc = (uint8_t const *) desc_itf;
|
||||
uint8_t const *p_desc = (uint8_t const *)desc_itf;
|
||||
|
||||
//------------- HID descriptor -------------//
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
TU_ASSERT(HID_DESC_TYPE_HID == tu_desc_type(p_desc), 0);
|
||||
p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *) p_desc;
|
||||
p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *)p_desc;
|
||||
|
||||
//------------- Endpoint Descriptor -------------//
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0);
|
||||
|
||||
if ( desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT ) p_hid->itf_protocol = desc_itf->bInterfaceProtocol;
|
||||
if (desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT)
|
||||
p_hid->itf_protocol = desc_itf->bInterfaceProtocol;
|
||||
|
||||
p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode
|
||||
p_hid->itf_num = desc_itf->bInterfaceNumber;
|
||||
p_hid->itf_num = desc_itf->bInterfaceNumber;
|
||||
|
||||
// Use offsetof to avoid pointer to the odd/misaligned address
|
||||
p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*) p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength));
|
||||
p_hid->report_desc_len = tu_unaligned_read16((uint8_t const *)p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength));
|
||||
|
||||
// Prepare for output endpoint
|
||||
if (p_hid->ep_out)
|
||||
{
|
||||
if ( !usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)) )
|
||||
{
|
||||
if (p_hid->ep_out) {
|
||||
if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))) {
|
||||
TU_LOG_FAILED();
|
||||
TU_BREAKPOINT();
|
||||
}
|
||||
@@ -252,144 +234,120 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint1
|
||||
// Invoked when a control transfer occurred on an interface of this class
|
||||
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
|
||||
bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
|
||||
{
|
||||
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
|
||||
|
||||
uint8_t const hid_itf = get_index_by_itfnum((uint8_t) request->wIndex);
|
||||
uint8_t const hid_itf = get_index_by_itfnum((uint8_t)request->wIndex);
|
||||
TU_VERIFY(hid_itf < CFG_TUD_HID);
|
||||
|
||||
hidd_interface_t* p_hid = &_hidd_itf[hid_itf];
|
||||
hidd_interface_t *p_hid = &_hidd_itf[hid_itf];
|
||||
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD)
|
||||
{
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
|
||||
//------------- STD Request -------------//
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
uint8_t const desc_type = tu_u16_high(request->wValue);
|
||||
//uint8_t const desc_index = tu_u16_low (request->wValue);
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
uint8_t const desc_type = tu_u16_high(request->wValue);
|
||||
// uint8_t const desc_index = tu_u16_low (request->wValue);
|
||||
|
||||
if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID)
|
||||
{
|
||||
if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_HID) {
|
||||
TU_VERIFY(p_hid->hid_descriptor);
|
||||
TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) p_hid->hid_descriptor, p_hid->hid_descriptor->bLength));
|
||||
}
|
||||
else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT)
|
||||
{
|
||||
uint8_t const * desc_report = tud_hid_descriptor_report_cb(hid_itf);
|
||||
tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_report, p_hid->report_desc_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
TU_VERIFY(tud_control_xfer(rhport, request, (void *)(uintptr_t)p_hid->hid_descriptor, p_hid->hid_descriptor->bLength));
|
||||
} else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) {
|
||||
uint8_t const *desc_report = tud_hid_descriptor_report_cb(hid_itf);
|
||||
tud_control_xfer(rhport, request, (void *)(uintptr_t)desc_report, p_hid->report_desc_len);
|
||||
} else {
|
||||
return false; // stall unsupported request
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS)
|
||||
{
|
||||
} else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
|
||||
//------------- Class Specific Request -------------//
|
||||
switch( request->bRequest )
|
||||
{
|
||||
case HID_REQ_CONTROL_GET_REPORT:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
uint8_t const report_type = tu_u16_high(request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(request->wValue);
|
||||
switch (request->bRequest) {
|
||||
case HID_REQ_CONTROL_GET_REPORT:
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
uint8_t const report_type = tu_u16_high(request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(request->wValue);
|
||||
|
||||
uint8_t* report_buf = p_hid->ctrl_buf;
|
||||
uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
|
||||
uint8_t *report_buf = p_hid->ctrl_buf;
|
||||
uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
|
||||
|
||||
uint16_t xferlen = 0;
|
||||
uint16_t xferlen = 0;
|
||||
|
||||
// If host request a specific Report ID, add ID to as 1 byte of response
|
||||
if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) )
|
||||
{
|
||||
*report_buf++ = report_id;
|
||||
req_len--;
|
||||
// If host request a specific Report ID, add ID to as 1 byte of response
|
||||
if ((report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1)) {
|
||||
*report_buf++ = report_id;
|
||||
req_len--;
|
||||
|
||||
xferlen++;
|
||||
}
|
||||
|
||||
xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len);
|
||||
TU_ASSERT( xferlen > 0 );
|
||||
|
||||
tud_control_xfer(rhport, request, p_hid->ctrl_buf, xferlen);
|
||||
xferlen++;
|
||||
}
|
||||
|
||||
xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t)report_type, report_buf, req_len);
|
||||
TU_ASSERT(xferlen > 0);
|
||||
|
||||
tud_control_xfer(rhport, request, p_hid->ctrl_buf, xferlen);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_SET_REPORT:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
TU_VERIFY(request->wLength <= sizeof(p_hid->ctrl_buf));
|
||||
tud_control_xfer(rhport, request, p_hid->ctrl_buf, request->wLength);
|
||||
case HID_REQ_CONTROL_SET_REPORT:
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
TU_VERIFY(request->wLength <= sizeof(p_hid->ctrl_buf));
|
||||
tud_control_xfer(rhport, request, p_hid->ctrl_buf, request->wLength);
|
||||
} else if (stage == CONTROL_STAGE_ACK) {
|
||||
uint8_t const report_type = tu_u16_high(request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(request->wValue);
|
||||
|
||||
uint8_t const *report_buf = p_hid->ctrl_buf;
|
||||
uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
|
||||
|
||||
// If host request a specific Report ID, extract report ID in buffer before invoking callback
|
||||
if ((report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0])) {
|
||||
report_buf++;
|
||||
report_len--;
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_ACK )
|
||||
{
|
||||
uint8_t const report_type = tu_u16_high(request->wValue);
|
||||
uint8_t const report_id = tu_u16_low(request->wValue);
|
||||
|
||||
uint8_t const* report_buf = p_hid->ctrl_buf;
|
||||
uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
|
||||
|
||||
// If host request a specific Report ID, extract report ID in buffer before invoking callback
|
||||
if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) )
|
||||
{
|
||||
report_buf++;
|
||||
report_len--;
|
||||
}
|
||||
|
||||
tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len);
|
||||
}
|
||||
tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t)report_type, report_buf, report_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_SET_IDLE:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
p_hid->idle_rate = tu_u16_high(request->wValue);
|
||||
if ( tud_hid_set_idle_cb )
|
||||
{
|
||||
// stall request if callback return false
|
||||
TU_VERIFY( tud_hid_set_idle_cb( hid_itf, p_hid->idle_rate) );
|
||||
}
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
case HID_REQ_CONTROL_SET_IDLE:
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
p_hid->idle_rate = tu_u16_high(request->wValue);
|
||||
if (tud_hid_set_idle_cb) {
|
||||
// stall request if callback return false
|
||||
TU_VERIFY(tud_hid_set_idle_cb(hid_itf, p_hid->idle_rate));
|
||||
}
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_GET_IDLE:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
// TODO idle rate of report
|
||||
tud_control_xfer(rhport, request, &p_hid->idle_rate, 1);
|
||||
}
|
||||
case HID_REQ_CONTROL_GET_IDLE:
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
// TODO idle rate of report
|
||||
tud_control_xfer(rhport, request, &p_hid->idle_rate, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_GET_PROTOCOL:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1);
|
||||
}
|
||||
case HID_REQ_CONTROL_GET_PROTOCOL:
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REQ_CONTROL_SET_PROTOCOL:
|
||||
if ( stage == CONTROL_STAGE_SETUP )
|
||||
{
|
||||
tud_control_status(rhport, request);
|
||||
}
|
||||
else if ( stage == CONTROL_STAGE_ACK )
|
||||
{
|
||||
p_hid->protocol_mode = (uint8_t) request->wValue;
|
||||
if (tud_hid_set_protocol_cb)
|
||||
{
|
||||
tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode);
|
||||
}
|
||||
case HID_REQ_CONTROL_SET_PROTOCOL:
|
||||
if (stage == CONTROL_STAGE_SETUP) {
|
||||
tud_control_status(rhport, request);
|
||||
} else if (stage == CONTROL_STAGE_ACK) {
|
||||
p_hid->protocol_mode = (uint8_t)request->wValue;
|
||||
if (tud_hid_set_protocol_cb) {
|
||||
tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: return false; // stall unsupported request
|
||||
default:
|
||||
return false; // stall unsupported request
|
||||
}
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
return false; // stall unsupported request
|
||||
}
|
||||
|
||||
@@ -398,31 +356,43 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
|
||||
|
||||
bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
||||
{
|
||||
(void) result;
|
||||
(void)result;
|
||||
|
||||
uint8_t instance = 0;
|
||||
hidd_interface_t * p_hid = _hidd_itf;
|
||||
hidd_interface_t *p_hid = _hidd_itf;
|
||||
|
||||
// Identify which interface to use
|
||||
for (instance = 0; instance < CFG_TUD_HID; instance++)
|
||||
{
|
||||
for (instance = 0; instance < CFG_TUD_HID; instance++) {
|
||||
p_hid = &_hidd_itf[instance];
|
||||
if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break;
|
||||
if ((ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in))
|
||||
break;
|
||||
}
|
||||
TU_ASSERT(instance < CFG_TUD_HID);
|
||||
|
||||
// Check if there was a problem
|
||||
if (XFER_RESULT_SUCCESS != result) { // Inform application about the issue
|
||||
if (tud_hid_report_fail_cb) {
|
||||
tud_hid_report_fail_cb(instance, ep_addr, (uint16_t)xferred_bytes);
|
||||
}
|
||||
|
||||
// Allow a new transfer to be received if issue happened on an OUT endpoint
|
||||
if (ep_addr == p_hid->ep_out) {
|
||||
// Prepare the OUT endpoint to be able to receive a new transfer
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sent report successfully
|
||||
if (ep_addr == p_hid->ep_in)
|
||||
{
|
||||
if (tud_hid_report_complete_cb)
|
||||
{
|
||||
tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t) xferred_bytes);
|
||||
if (ep_addr == p_hid->ep_in) {
|
||||
if (tud_hid_report_complete_cb) {
|
||||
tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t)xferred_bytes);
|
||||
}
|
||||
}
|
||||
// Received report
|
||||
else if (ep_addr == p_hid->ep_out)
|
||||
{
|
||||
tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_INVALID, p_hid->epout_buf, (uint16_t) xferred_bytes);
|
||||
// Received report successfully
|
||||
else if (ep_addr == p_hid->ep_out) {
|
||||
tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t)xferred_bytes);
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
|
||||
}
|
||||
|
||||
|
||||
@@ -128,6 +128,8 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate);
|
||||
// Note: For composite reports, report[0] is report ID
|
||||
TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len);
|
||||
|
||||
// Invoked when a transfer wasn't successful
|
||||
TU_ATTR_WEAK void tud_hid_report_fail_cb(uint8_t instance, uint8_t ep_addr, uint16_t len);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Inline Functions
|
||||
@@ -471,6 +473,7 @@ uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf
|
||||
bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021, Ha Thach (tinyusb.org)
|
||||
* Copyright (c) 2024, Hardy Griech
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -24,22 +25,58 @@
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _TUSB_NCM_H_
|
||||
#define _TUSB_NCM_H_
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
// NTB buffers size for reception side, must be >> MTU to avoid TCP retransmission (driver issue ?)
|
||||
// Linux use 2048 as minimal size
|
||||
#ifndef CFG_TUD_NCM_OUT_NTB_MAX_SIZE
|
||||
#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200
|
||||
#endif
|
||||
|
||||
// Table 4.3 Data Class Interface Protocol Codes
|
||||
typedef enum
|
||||
{
|
||||
NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01
|
||||
} ncm_data_interface_protocol_code_t;
|
||||
// NTB buffers size for reception side, must be > MTU
|
||||
// Linux use 2048 as minimal size
|
||||
#ifndef CFG_TUD_NCM_IN_NTB_MAX_SIZE
|
||||
#define CFG_TUD_NCM_IN_NTB_MAX_SIZE 3200
|
||||
#endif
|
||||
|
||||
// Number of NTB buffers for reception side
|
||||
// Depending on the configuration, this parameter could be increased with the cost of additional RAM requirements
|
||||
// On Full-Speed (RP2040) :
|
||||
// 1 - good performance
|
||||
// 2 - up to 30% more performance with iperf with small packets
|
||||
// >2 - no performance gain
|
||||
// On High-Speed (STM32F7) :
|
||||
// No performance gain
|
||||
#ifndef CFG_TUD_NCM_OUT_NTB_N
|
||||
#define CFG_TUD_NCM_OUT_NTB_N 1
|
||||
#endif
|
||||
|
||||
// Number of NTB buffers for transmission side
|
||||
// Depending on the configuration, this parameter could be increased with the cost of additional RAM requirements
|
||||
// On Full-Speed (RP2040) :
|
||||
// 1 - good performance but SystemView shows lost events (on load test)
|
||||
// 2 - up to 50% more performance with iperf with small packets, "tud_network_can_xmit: request blocked"
|
||||
// happens from time to time with SystemView
|
||||
// 3 - "tud_network_can_xmit: request blocked" never happens
|
||||
// >3 - no performance gain
|
||||
// On High-Speed (STM32F7) :
|
||||
// No performance gain
|
||||
#ifndef CFG_TUD_NCM_IN_NTB_N
|
||||
#define CFG_TUD_NCM_IN_NTB_N 1
|
||||
#endif
|
||||
|
||||
// How many datagrams it is allowed to put into an NTB for transmission side
|
||||
#ifndef CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB
|
||||
#define CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB 8
|
||||
#endif
|
||||
|
||||
// This tells the host how many datagrams it is allowed to put into an NTB
|
||||
#ifndef CFG_TUD_NCM_OUT_MAX_DATAGRAMS_PER_NTB
|
||||
#define CFG_TUD_NCM_OUT_MAX_DATAGRAMS_PER_NTB 6
|
||||
#endif
|
||||
|
||||
// Table 6.2 Class-Specific Request Codes for Network Control Model subclass
|
||||
typedef enum
|
||||
@@ -62,8 +99,65 @@ typedef enum
|
||||
NCM_SET_CRC_MODE = 0x8A,
|
||||
} ncm_request_code_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define NTH16_SIGNATURE 0x484D434E
|
||||
#define NDP16_SIGNATURE_NCM0 0x304D434E
|
||||
#define NDP16_SIGNATURE_NCM1 0x314D434E
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint16_t wLength;
|
||||
uint16_t bmNtbFormatsSupported;
|
||||
uint32_t dwNtbInMaxSize;
|
||||
uint16_t wNdbInDivisor;
|
||||
uint16_t wNdbInPayloadRemainder;
|
||||
uint16_t wNdbInAlignment;
|
||||
uint16_t wReserved;
|
||||
uint32_t dwNtbOutMaxSize;
|
||||
uint16_t wNdbOutDivisor;
|
||||
uint16_t wNdbOutPayloadRemainder;
|
||||
uint16_t wNdbOutAlignment;
|
||||
uint16_t wNtbOutMaxDatagrams;
|
||||
} ntb_parameters_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t dwSignature;
|
||||
uint16_t wHeaderLength;
|
||||
uint16_t wSequence;
|
||||
uint16_t wBlockLength;
|
||||
uint16_t wNdpIndex;
|
||||
} nth16_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint16_t wDatagramIndex;
|
||||
uint16_t wDatagramLength;
|
||||
} ndp16_datagram_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t dwSignature;
|
||||
uint16_t wLength;
|
||||
uint16_t wNextNdpIndex;
|
||||
//ndp16_datagram_t datagram[];
|
||||
} ndp16_t;
|
||||
|
||||
typedef union TU_ATTR_PACKED {
|
||||
struct {
|
||||
nth16_t nth;
|
||||
ndp16_t ndp;
|
||||
ndp16_datagram_t ndp_datagram[CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB + 1];
|
||||
};
|
||||
uint8_t data[CFG_TUD_NCM_IN_NTB_MAX_SIZE];
|
||||
} xmit_ntb_t;
|
||||
|
||||
typedef union TU_ATTR_PACKED {
|
||||
struct {
|
||||
nth16_t nth;
|
||||
// only the header is at a guaranteed position
|
||||
};
|
||||
uint8_t data[CFG_TUD_NCM_OUT_NTB_MAX_SIZE];
|
||||
} recv_ntb_t;
|
||||
|
||||
struct ncm_notify_t {
|
||||
tusb_control_request_t header;
|
||||
uint32_t downlink, uplink;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,14 +28,13 @@
|
||||
#ifndef _TUSB_NET_DEVICE_H_
|
||||
#define _TUSB_NET_DEVICE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "class/cdc/cdc.h"
|
||||
|
||||
#if CFG_TUD_ECM_RNDIS && CFG_TUD_NCM
|
||||
#error "Cannot enable both ECM_RNDIS and NCM network drivers"
|
||||
#endif
|
||||
|
||||
#include "ncm.h"
|
||||
|
||||
/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */
|
||||
#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
|
||||
@@ -44,21 +43,13 @@
|
||||
#define CFG_TUD_NET_MTU 1514
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_NCM_IN_NTB_MAX_SIZE
|
||||
#define CFG_TUD_NCM_IN_NTB_MAX_SIZE 3200
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_NCM_OUT_NTB_MAX_SIZE
|
||||
#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE 3200
|
||||
#endif
|
||||
// Table 4.3 Data Class Interface Protocol Codes
|
||||
typedef enum
|
||||
{
|
||||
NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01
|
||||
} ncm_data_interface_protocol_code_t;
|
||||
|
||||
#ifndef CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB
|
||||
#define CFG_TUD_NCM_MAX_DATAGRAMS_PER_NTB 8
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_NCM_ALIGNMENT
|
||||
#define CFG_TUD_NCM_ALIGNMENT 4
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -96,11 +87,6 @@ void tud_network_init_cb(void);
|
||||
// TODO removed later since it is not part of tinyusb stack
|
||||
extern uint8_t tud_network_mac_address[6];
|
||||
|
||||
//------------- NCM -------------//
|
||||
|
||||
// callback to client providing optional indication of internal state of network driver
|
||||
void tud_network_link_state_cb(bool state);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL USBD-CLASS DRIVER API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@@ -183,6 +183,23 @@ typedef enum {
|
||||
|
||||
} usmtmc_request_type_enum;
|
||||
|
||||
typedef enum {
|
||||
// The last and first valid bNotify1 for use by the USBTMC class specification.
|
||||
USBTMC_bNOTIFY1_USBTMC_FIRST = 0x00,
|
||||
USBTMC_bNOTIFY1_USBTMC_LAST = 0x3F,
|
||||
|
||||
// The last and first valid bNotify1 for use by vendors.
|
||||
USBTMC_bNOTIFY1_VENDOR_SPECIFIC_FIRST = 0x40,
|
||||
USBTMC_bNOTIFY1_VENDOR_SPECIFIC_LAST = 0x7F,
|
||||
|
||||
// The last and first valid bNotify1 for use by USBTMC subclass specifications.
|
||||
USBTMC_bNOTIFY1_SUBCLASS_FIRST = 0x80,
|
||||
USBTMC_bNOTIFY1_SUBCLASS_LAST = 0xFF,
|
||||
|
||||
// From the USB488 Subclass Specification, Section 3.4.
|
||||
USB488_bNOTIFY1_SRQ = 0x81,
|
||||
} usbtmc_int_in_payload_format;
|
||||
|
||||
typedef enum {
|
||||
USBTMC_STATUS_SUCCESS = 0x01,
|
||||
USBTMC_STATUS_PENDING = 0x02,
|
||||
@@ -303,6 +320,14 @@ typedef struct TU_ATTR_PACKED
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(usbtmc_read_stb_rsp_488_t) == 3u, "struct wrong length");
|
||||
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint8_t bNotify1; // Must be USB488_bNOTIFY1_SRQ
|
||||
uint8_t StatusByte;
|
||||
} usbtmc_srq_interrupt_488_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(usbtmc_srq_interrupt_488_t) == 2u, "struct wrong length");
|
||||
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
struct TU_ATTR_PACKED
|
||||
|
||||
@@ -86,6 +86,11 @@ tu_static char logMsg[150];
|
||||
// imposes a minimum buffer size of 32 bytes.
|
||||
#define USBTMCD_BUFFER_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
|
||||
// Interrupt endpoint buffer size, default to 2 bytes as USB488 specification.
|
||||
#ifndef CFG_TUD_USBTMC_INT_EP_SIZE
|
||||
#define CFG_TUD_USBTMC_INT_EP_SIZE 2
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The state machine does not allow simultaneous reading and writing. This is
|
||||
* consistent with USBTMC.
|
||||
@@ -124,13 +129,15 @@ typedef struct
|
||||
uint8_t ep_bulk_in;
|
||||
uint8_t ep_bulk_out;
|
||||
uint8_t ep_int_in;
|
||||
uint32_t ep_bulk_in_wMaxPacketSize;
|
||||
uint32_t ep_bulk_out_wMaxPacketSize;
|
||||
// IN buffer is only used for first packet, not the remainder
|
||||
// in order to deal with prepending header
|
||||
CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_BUFFER_SIZE];
|
||||
uint32_t ep_bulk_in_wMaxPacketSize;
|
||||
// OUT buffer receives one packet at a time
|
||||
CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_BUFFER_SIZE];
|
||||
uint32_t ep_bulk_out_wMaxPacketSize;
|
||||
// Buffer int msg to ensure alignment and placement correctness
|
||||
CFG_TUSB_MEM_ALIGN uint8_t ep_int_in_buf[CFG_TUD_USBTMC_INT_EP_SIZE];
|
||||
|
||||
uint32_t transfer_size_remaining; // also used for requested length for bulk IN.
|
||||
uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes)
|
||||
@@ -240,6 +247,19 @@ bool tud_usbtmc_transmit_dev_msg_data(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tud_usbtmc_transmit_notification_data(const void * data, size_t len)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
TU_ASSERT(len > 0);
|
||||
TU_ASSERT(usbtmc_state.ep_int_in != 0);
|
||||
#endif
|
||||
TU_VERIFY(usbd_edpt_busy(usbtmc_state.rhport, usbtmc_state.ep_int_in));
|
||||
|
||||
TU_VERIFY(tu_memcpy_s(usbtmc_state.ep_int_in_buf, sizeof(usbtmc_state.ep_int_in_buf), data, len) == 0);
|
||||
TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_int_in, usbtmc_state.ep_int_in_buf, (uint16_t)len));
|
||||
return true;
|
||||
}
|
||||
|
||||
void usbtmcd_init_cb(void)
|
||||
{
|
||||
usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb();
|
||||
@@ -547,9 +567,10 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
|
||||
case STATE_TX_INITIATED:
|
||||
if(usbtmc_state.transfer_size_remaining >= sizeof(usbtmc_state.ep_bulk_in_buf))
|
||||
{
|
||||
// FIXME! This removes const below!
|
||||
// Copy buffer to ensure alignment correctness
|
||||
memcpy(usbtmc_state.ep_bulk_in_buf, usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf));
|
||||
TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in,
|
||||
(void*)(uintptr_t) usbtmc_state.devInBuffer, sizeof(usbtmc_state.ep_bulk_in_buf)));
|
||||
usbtmc_state.ep_bulk_in_buf, sizeof(usbtmc_state.ep_bulk_in_buf)));
|
||||
usbtmc_state.devInBuffer += sizeof(usbtmc_state.ep_bulk_in_buf);
|
||||
usbtmc_state.transfer_size_remaining -= sizeof(usbtmc_state.ep_bulk_in_buf);
|
||||
usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.ep_bulk_in_buf);
|
||||
@@ -585,7 +606,9 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
|
||||
}
|
||||
}
|
||||
else if (ep_addr == usbtmc_state.ep_int_in) {
|
||||
// Good?
|
||||
if (tud_usbtmc_notification_complete_cb) {
|
||||
TU_VERIFY(tud_usbtmc_notification_complete_cb());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -73,6 +73,10 @@ bool tud_usbtmc_check_abort_bulk_in_cb(usbtmc_check_abort_bulk_rsp_t *rsp);
|
||||
bool tud_usbtmc_check_abort_bulk_out_cb(usbtmc_check_abort_bulk_rsp_t *rsp);
|
||||
bool tud_usbtmc_check_clear_cb(usbtmc_get_clear_status_rsp_t *rsp);
|
||||
|
||||
// The interrupt-IN endpoint buffer was transmitted to the host. Use
|
||||
// tud_usbtmc_transmit_notification_data to send another notification.
|
||||
TU_ATTR_WEAK bool tud_usbtmc_notification_complete_cb(void);
|
||||
|
||||
// Indicator pulse should be 0.5 to 1.0 seconds long
|
||||
TU_ATTR_WEAK bool tud_usbtmc_indicator_pulse_cb(tusb_control_request_t const * msg, uint8_t *tmcResult);
|
||||
|
||||
@@ -82,17 +86,23 @@ TU_ATTR_WEAK bool tud_usbtmc_msg_trigger_cb(usbtmc_msg_generic_t* msg);
|
||||
//TU_ATTR_WEAK bool tud_usbtmc_app_go_to_local_cb();
|
||||
#endif
|
||||
|
||||
/*******************************************
|
||||
* Called from app
|
||||
*
|
||||
* We keep a reference to the buffer, so it MUST not change until the app is
|
||||
* notified that the transfer is complete.
|
||||
******************************************/
|
||||
|
||||
// Called from app
|
||||
//
|
||||
// We keep a reference to the buffer, so it MUST not change until the app is
|
||||
// notified that the transfer is complete.
|
||||
bool tud_usbtmc_transmit_dev_msg_data(
|
||||
const void * data, size_t len,
|
||||
bool endOfMessage, bool usingTermChar);
|
||||
|
||||
// Buffers a notification to be sent to the host. The data starts
|
||||
// with the bNotify1 field, see the USBTMC Specification, Table 13.
|
||||
//
|
||||
// If the previous notification data has not yet been sent, this
|
||||
// returns false.
|
||||
//
|
||||
// Requires an interrupt endpoint in the interface.
|
||||
bool tud_usbtmc_transmit_notification_data(const void * data, size_t len);
|
||||
|
||||
bool tud_usbtmc_start_bus_read(void);
|
||||
|
||||
|
||||
@@ -105,9 +115,4 @@ void usbtmcd_reset_cb(uint8_t rhport);
|
||||
bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||
|
||||
/************************************************************
|
||||
* USBTMC Descriptor Templates
|
||||
*************************************************************/
|
||||
|
||||
|
||||
#endif /* CLASS_USBTMC_USBTMC_DEVICE_H_ */
|
||||
|
||||
Reference in New Issue
Block a user