Merge branch 'master' into remove-dcd-set-config
This commit is contained in:
@@ -223,11 +223,11 @@ void cdcd_reset(uint8_t rhport)
|
||||
bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
|
||||
{
|
||||
// Only support ACM subclass
|
||||
TU_ASSERT ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass);
|
||||
TU_VERIFY ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
|
||||
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass);
|
||||
|
||||
// Only support AT commands, no protocol and vendor specific commands.
|
||||
TU_ASSERT(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) ||
|
||||
itf_desc->bInterfaceProtocol == 0xff);
|
||||
// Note: 0xFF can be used with RNDIS
|
||||
TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA));
|
||||
|
||||
// Find available interface
|
||||
cdcd_interface_t * p_cdc = NULL;
|
||||
@@ -262,12 +262,12 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
|
||||
|
||||
p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
|
||||
|
||||
(*p_length) += p_desc[DESC_OFFSET_LEN];
|
||||
(*p_length) += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
|
||||
//------------- Data Interface (if any) -------------//
|
||||
if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) &&
|
||||
if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
|
||||
(TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
|
||||
{
|
||||
// next to endpoint descriptor
|
||||
|
||||
@@ -86,7 +86,7 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr)
|
||||
{
|
||||
// TODO consider all AT Command as serial candidate
|
||||
return tuh_cdc_mounted(dev_addr) &&
|
||||
(CDC_COMM_PROTOCOL_ATCOMMAND <= cdch_data[dev_addr-1].itf_protocol) &&
|
||||
(CDC_COMM_PROTOCOL_NONE <= cdch_data[dev_addr-1].itf_protocol) &&
|
||||
(cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16
|
||||
(void) rhport;
|
||||
|
||||
// Ensure this is DFU Runtime
|
||||
TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS);
|
||||
TU_ASSERT(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT);
|
||||
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS);
|
||||
TU_VERIFY(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT);
|
||||
|
||||
uint8_t const * p_desc = tu_desc_next( itf_desc );
|
||||
(*p_length) = sizeof(tusb_desc_interface_t);
|
||||
|
||||
@@ -58,7 +58,7 @@ typedef enum
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when received new data
|
||||
TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void);
|
||||
TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb convention
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
|
||||
@@ -160,6 +160,8 @@ void hidd_reset(uint8_t rhport)
|
||||
|
||||
bool hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_len)
|
||||
{
|
||||
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass);
|
||||
|
||||
uint8_t const *p_desc = (uint8_t const *) desc_itf;
|
||||
|
||||
// Find available interface
|
||||
|
||||
@@ -253,21 +253,31 @@ void midid_reset(uint8_t rhport)
|
||||
}
|
||||
}
|
||||
|
||||
bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length)
|
||||
bool midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length)
|
||||
{
|
||||
// For now handle the audio control interface as well.
|
||||
if ( AUDIO_SUBCLASS_CONTROL == p_interface_desc->bInterfaceSubClass) {
|
||||
uint8_t const * p_desc = tu_desc_next ( (uint8_t const *) p_interface_desc );
|
||||
(*p_length) = sizeof(tusb_desc_interface_t);
|
||||
|
||||
// Skip over the class specific descriptor.
|
||||
(*p_length) += tu_desc_len(p_desc);
|
||||
// 1st Interface is Audio Control v1
|
||||
TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
|
||||
AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
|
||||
AUDIO_PROTOCOL_V1 == desc_itf->bInterfaceProtocol);
|
||||
|
||||
uint16_t drv_len = tu_desc_len(desc_itf);
|
||||
uint8_t const * p_desc = tu_desc_next(desc_itf);
|
||||
|
||||
// Skip Class Specific descriptors
|
||||
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
|
||||
{
|
||||
drv_len += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
return true;
|
||||
}
|
||||
|
||||
TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == p_interface_desc->bInterfaceSubClass &&
|
||||
AUDIO_PROTOCOL_V1 == p_interface_desc->bInterfaceProtocol );
|
||||
// 2nd Interface is MIDI Streaming
|
||||
TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc));
|
||||
tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc;
|
||||
|
||||
TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass &&
|
||||
AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass &&
|
||||
AUDIO_PROTOCOL_V1 == desc_midi->bInterfaceProtocol );
|
||||
|
||||
// Find available interface
|
||||
midid_interface_t * p_midi = NULL;
|
||||
@@ -280,13 +290,15 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc,
|
||||
}
|
||||
}
|
||||
|
||||
p_midi->itf_num = p_interface_desc->bInterfaceNumber;
|
||||
p_midi->itf_num = desc_midi->bInterfaceNumber;
|
||||
|
||||
uint8_t const * p_desc = tu_desc_next( (uint8_t const *) p_interface_desc );
|
||||
(*p_length) = sizeof(tusb_desc_interface_t);
|
||||
// next descriptor
|
||||
drv_len += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
|
||||
// Find and open endpoint descriptors
|
||||
uint8_t found_endpoints = 0;
|
||||
while (found_endpoints < p_interface_desc->bNumEndpoints)
|
||||
while (found_endpoints < desc_midi->bNumEndpoints)
|
||||
{
|
||||
if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
|
||||
{
|
||||
@@ -298,14 +310,16 @@ bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc,
|
||||
p_midi->ep_out = ep_addr;
|
||||
}
|
||||
|
||||
(*p_length) += p_desc[DESC_OFFSET_LEN];
|
||||
drv_len += p_desc[DESC_OFFSET_LEN];
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
found_endpoints += 1;
|
||||
}
|
||||
(*p_length) += p_desc[DESC_OFFSET_LEN];
|
||||
drv_len += p_desc[DESC_OFFSET_LEN];
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
|
||||
*p_length = drv_len;
|
||||
|
||||
// Prepare for incoming data
|
||||
TU_ASSERT( usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false);
|
||||
|
||||
|
||||
@@ -157,7 +157,8 @@ void mscd_reset(uint8_t rhport)
|
||||
bool mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len)
|
||||
{
|
||||
// only support SCSI's BOT protocol
|
||||
TU_ASSERT(MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass &&
|
||||
TU_VERIFY(TUSB_CLASS_MSC == itf_desc->bInterfaceClass &&
|
||||
MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass &&
|
||||
MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol);
|
||||
|
||||
mscd_interface_t * p_msc = &_mscd_itf;
|
||||
|
||||
+229
-138
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "tusb_option.h"
|
||||
|
||||
#if ( TUSB_OPT_DEVICE_ENABLED && (CFG_TUD_NET != OPT_NET_NONE) )
|
||||
#if ( TUSB_OPT_DEVICE_ENABLED && CFG_TUD_NET )
|
||||
|
||||
#include "net_device.h"
|
||||
#include "device/usbd_pvt.h"
|
||||
@@ -40,40 +40,60 @@ void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networ
|
||||
//--------------------------------------------------------------------+
|
||||
typedef struct
|
||||
{
|
||||
uint8_t itf_num;
|
||||
uint8_t itf_num; // Index number of Management Interface, +1 for Data Interface
|
||||
uint8_t itf_data_alt; // Alternate setting of Data Interface. 0 : inactive, 1 : active
|
||||
|
||||
uint8_t ep_notif;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
|
||||
bool ecm_mode;
|
||||
|
||||
// Endpoint descriptor use to open/close when receving SetInterface
|
||||
// TODO since configuration descriptor may not be long-lived memory, we should
|
||||
// keep a copy of endpoint attribute instead
|
||||
uint8_t const * ecm_desc_epdata;
|
||||
|
||||
} netd_interface_t;
|
||||
|
||||
#if CFG_TUD_NET == OPT_NET_ECM
|
||||
#define CFG_TUD_NET_PACKET_PREFIX_LEN 0
|
||||
#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0
|
||||
#define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL
|
||||
#elif CFG_TUD_NET == OPT_NET_RNDIS
|
||||
#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t)
|
||||
#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0
|
||||
#define CFG_TUD_NET_INTERFACESUBCLASS TUD_RNDIS_ITF_SUBCLASS
|
||||
#elif CFG_TUD_NET == OPT_NET_EEM
|
||||
#define CFG_TUD_NET_PACKET_PREFIX_LEN 2
|
||||
#define CFG_TUD_NET_PACKET_SUFFIX_LEN 4
|
||||
#define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL
|
||||
#endif
|
||||
#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t)
|
||||
#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0
|
||||
|
||||
CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN];
|
||||
CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN];
|
||||
|
||||
#if CFG_TUD_NET == OPT_NET_ECM
|
||||
CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static tusb_control_request_t notify =
|
||||
{
|
||||
.bmRequestType = 0x21,
|
||||
.bRequest = 0 /* NETWORK_CONNECTION */,
|
||||
struct ecm_notify_struct
|
||||
{
|
||||
tusb_control_request_t header;
|
||||
uint32_t downlink, uplink;
|
||||
};
|
||||
|
||||
static const struct ecm_notify_struct ecm_notify_nc =
|
||||
{
|
||||
.header = {
|
||||
.bmRequestType = 0xA1,
|
||||
.bRequest = 0 /* NETWORK_CONNECTION aka NetworkConnection */,
|
||||
.wValue = 1 /* Connected */,
|
||||
.wLength = 0,
|
||||
};
|
||||
#elif CFG_TUD_NET == OPT_NET_RNDIS
|
||||
CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[120];
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ecm_notify_struct ecm_notify_csc =
|
||||
{
|
||||
.header = {
|
||||
.bmRequestType = 0xA1,
|
||||
.bRequest = 0x2A /* CONNECTION_SPEED_CHANGE aka ConnectionSpeedChange */,
|
||||
.wLength = 8,
|
||||
},
|
||||
.downlink = 9728000,
|
||||
.uplink = 9728000,
|
||||
};
|
||||
|
||||
CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static union
|
||||
{
|
||||
uint8_t rndis_buf[120];
|
||||
struct ecm_notify_struct ecm_buf;
|
||||
} notify;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL OBJECT & FUNCTION DECLARATION
|
||||
@@ -115,19 +135,28 @@ void netd_reset(uint8_t rhport)
|
||||
|
||||
bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
|
||||
{
|
||||
// sanity check the descriptor
|
||||
TU_ASSERT (CFG_TUD_NET_INTERFACESUBCLASS == itf_desc->bInterfaceSubClass);
|
||||
bool const is_rndis = (TUD_RNDIS_ITF_CLASS == itf_desc->bInterfaceClass &&
|
||||
TUD_RNDIS_ITF_SUBCLASS == itf_desc->bInterfaceSubClass &&
|
||||
TUD_RNDIS_ITF_PROTOCOL == itf_desc->bInterfaceProtocol);
|
||||
|
||||
bool const is_ecm = (TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
|
||||
CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL == itf_desc->bInterfaceSubClass &&
|
||||
0x00 == itf_desc->bInterfaceProtocol);
|
||||
|
||||
TU_VERIFY ( is_rndis || is_ecm );
|
||||
|
||||
// confirm interface hasn't already been allocated
|
||||
TU_ASSERT(0 == _netd_itf.ep_in);
|
||||
TU_ASSERT(0 == _netd_itf.ep_notif);
|
||||
|
||||
//------------- first Interface -------------//
|
||||
// sanity check the descriptor
|
||||
_netd_itf.ecm_mode = is_ecm;
|
||||
|
||||
//------------- Management Interface -------------//
|
||||
_netd_itf.itf_num = itf_desc->bInterfaceNumber;
|
||||
|
||||
uint8_t const * p_desc = tu_desc_next( itf_desc );
|
||||
(*p_length) = sizeof(tusb_desc_interface_t);
|
||||
uint8_t const * p_desc = tu_desc_next( itf_desc );
|
||||
|
||||
#if CFG_TUD_NET != OPT_NET_EEM
|
||||
// Communication Functional Descriptors
|
||||
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
|
||||
{
|
||||
@@ -142,35 +171,49 @@ bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
|
||||
|
||||
_netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
|
||||
|
||||
(*p_length) += p_desc[DESC_OFFSET_LEN];
|
||||
(*p_length) += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
|
||||
//------------- second Interface -------------//
|
||||
if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) &&
|
||||
(TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
|
||||
{
|
||||
// next to endpoint descriptor
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
(*p_length) += sizeof(tusb_desc_interface_t);
|
||||
}
|
||||
#endif
|
||||
//------------- Data Interface -------------//
|
||||
// - RNDIS Data followed immediately by a pair of endpoints
|
||||
// - CDC-ECM data interface has 2 alternate settings
|
||||
// - 0 : zero endpoints for inactive (default)
|
||||
// - 1 : IN & OUT endpoints for active networking
|
||||
TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc));
|
||||
|
||||
if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
|
||||
do
|
||||
{
|
||||
// Open endpoint pair
|
||||
tusb_desc_interface_t const * data_itf_desc = (tusb_desc_interface_t const *) p_desc;
|
||||
TU_ASSERT(TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass);
|
||||
|
||||
(*p_length) += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}while( _netd_itf.ecm_mode && (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) );
|
||||
|
||||
// Pair of endpoints
|
||||
TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc));
|
||||
|
||||
if ( _netd_itf.ecm_mode )
|
||||
{
|
||||
// ECM by default is in-active, save the endpoint attribute
|
||||
// to open later when received setInterface
|
||||
_netd_itf.ecm_desc_epdata = p_desc;
|
||||
}else
|
||||
{
|
||||
// Open endpoint pair for RNDIS
|
||||
TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) );
|
||||
|
||||
(*p_length) += 2*sizeof(tusb_desc_endpoint_t);
|
||||
tud_network_init_cb();
|
||||
|
||||
// we are ready to transmit a packet
|
||||
can_xmit = true;
|
||||
|
||||
// prepare for incoming packets
|
||||
tud_network_recv_renew();
|
||||
}
|
||||
|
||||
tud_network_init_cb();
|
||||
|
||||
// we are ready to transmit a packet
|
||||
can_xmit = true;
|
||||
|
||||
// prepare for incoming packets
|
||||
tud_network_recv_renew();
|
||||
(*p_length) += 2*sizeof(tusb_desc_endpoint_t);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -181,116 +224,167 @@ bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * reques
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// Handle class request only
|
||||
TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
|
||||
TU_VERIFY (_netd_itf.itf_num == request->wIndex);
|
||||
|
||||
#if CFG_TUD_NET == OPT_NET_RNDIS
|
||||
if (request->bmRequestType_bit.direction == TUSB_DIR_OUT)
|
||||
// Handle RNDIS class control OUT only
|
||||
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS &&
|
||||
request->bmRequestType_bit.direction == TUSB_DIR_OUT &&
|
||||
_netd_itf.itf_num == request->wIndex)
|
||||
{
|
||||
rndis_class_set_handler(rndis_buf, request->wLength);
|
||||
if ( !_netd_itf.ecm_mode )
|
||||
{
|
||||
rndis_class_set_handler(notify.rndis_buf, request->wLength);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ecm_report(bool nc)
|
||||
{
|
||||
notify.ecm_buf = (nc) ? ecm_notify_nc : ecm_notify_csc;
|
||||
notify.ecm_buf.header.wIndex = _netd_itf.itf_num;
|
||||
netd_report((uint8_t *)¬ify.ecm_buf, (nc) ? sizeof(notify.ecm_buf.header) : sizeof(notify.ecm_buf));
|
||||
}
|
||||
|
||||
// Handle class control request
|
||||
// return false to stall control endpoint (e.g unsupported request)
|
||||
bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request)
|
||||
{
|
||||
// Handle class request only
|
||||
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
|
||||
switch ( request->bmRequestType_bit.type )
|
||||
{
|
||||
case TUSB_REQ_TYPE_STANDARD:
|
||||
switch ( request->bRequest )
|
||||
{
|
||||
case TUSB_REQ_GET_INTERFACE:
|
||||
{
|
||||
uint8_t const req_itfnum = (uint8_t) request->wIndex;
|
||||
TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum);
|
||||
|
||||
TU_VERIFY (_netd_itf.itf_num == request->wIndex);
|
||||
tud_control_xfer(rhport, request, &_netd_itf.itf_data_alt, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
#if CFG_TUD_NET == OPT_NET_ECM
|
||||
/* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */
|
||||
if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest)
|
||||
{
|
||||
tud_control_xfer(rhport, request, NULL, 0);
|
||||
notify.wIndex = request->wIndex;
|
||||
usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, (uint8_t *)¬ify, sizeof(notify));
|
||||
case TUSB_REQ_SET_INTERFACE:
|
||||
{
|
||||
uint8_t const req_itfnum = (uint8_t) request->wIndex;
|
||||
uint8_t const req_alt = (uint8_t) request->wValue;
|
||||
|
||||
// Only valid for Data Interface with Alternate is either 0 or 1
|
||||
TU_VERIFY(_netd_itf.itf_num+1 == req_itfnum && req_alt < 2);
|
||||
|
||||
// ACM-ECM only: qequest to enable/disable network activities
|
||||
TU_VERIFY(_netd_itf.ecm_mode);
|
||||
|
||||
_netd_itf.itf_data_alt = req_alt;
|
||||
|
||||
if ( _netd_itf.itf_data_alt )
|
||||
{
|
||||
// TODO since we don't actually close endpoint
|
||||
// hack here to not re-open it
|
||||
if ( _netd_itf.ep_in == 0 && _netd_itf.ep_out == 0 )
|
||||
{
|
||||
TU_ASSERT(_netd_itf.ecm_desc_epdata);
|
||||
TU_ASSERT( usbd_open_edpt_pair(rhport, _netd_itf.ecm_desc_epdata, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) );
|
||||
|
||||
// TODO should be merge with RNDIS's after endpoint opened
|
||||
// Also should have opposite callback for application to disable network !!
|
||||
tud_network_init_cb();
|
||||
can_xmit = true; // we are ready to transmit a packet
|
||||
tud_network_recv_renew(); // prepare for incoming packets
|
||||
}
|
||||
}else
|
||||
{
|
||||
// TODO close the endpoint pair
|
||||
// For now pretend that we did, this should have no harm since host won't try to
|
||||
// communicate with the endpoints again
|
||||
// _netd_itf.ep_in = _netd_itf.ep_out = 0
|
||||
}
|
||||
|
||||
tud_control_status(rhport, request);
|
||||
}
|
||||
break;
|
||||
|
||||
// unsupported request
|
||||
default: return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case TUSB_REQ_TYPE_CLASS:
|
||||
TU_VERIFY (_netd_itf.itf_num == request->wIndex);
|
||||
|
||||
if (_netd_itf.ecm_mode)
|
||||
{
|
||||
/* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */
|
||||
if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest)
|
||||
{
|
||||
tud_control_xfer(rhport, request, NULL, 0);
|
||||
ecm_report(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request->bmRequestType_bit.direction == TUSB_DIR_IN)
|
||||
{
|
||||
rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)notify.rndis_buf;
|
||||
uint32_t msglen = tu_le32toh(rndis_msg->MessageLength);
|
||||
TU_ASSERT(msglen <= sizeof(notify.rndis_buf));
|
||||
tud_control_xfer(rhport, request, notify.rndis_buf, msglen);
|
||||
}
|
||||
else
|
||||
{
|
||||
tud_control_xfer(rhport, request, notify.rndis_buf, sizeof(notify.rndis_buf));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// unsupported request
|
||||
default: return false;
|
||||
}
|
||||
#elif CFG_TUD_NET == OPT_NET_RNDIS
|
||||
if (request->bmRequestType_bit.direction == TUSB_DIR_IN)
|
||||
{
|
||||
rndis_generic_msg_t *rndis_msg = (rndis_generic_msg_t *)rndis_buf;
|
||||
uint32_t msglen = tu_le32toh(rndis_msg->MessageLength);
|
||||
TU_ASSERT(msglen <= sizeof(rndis_buf));
|
||||
tud_control_xfer(rhport, request, rndis_buf, msglen);
|
||||
}
|
||||
else
|
||||
{
|
||||
tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf));
|
||||
}
|
||||
#else
|
||||
(void)rhport;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct cdc_eem_packet_header
|
||||
{
|
||||
uint16_t length:14;
|
||||
uint16_t bmCRC:1;
|
||||
uint16_t bmType:1;
|
||||
};
|
||||
|
||||
static void handle_incoming_packet(uint32_t len)
|
||||
{
|
||||
uint8_t *pnt = received;
|
||||
uint32_t size = 0;
|
||||
|
||||
#if CFG_TUD_NET == OPT_NET_ECM
|
||||
size = len;
|
||||
#elif CFG_TUD_NET == OPT_NET_RNDIS
|
||||
rndis_data_packet_t *r = (rndis_data_packet_t *)pnt;
|
||||
if (len >= sizeof(rndis_data_packet_t))
|
||||
if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len))
|
||||
if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len)
|
||||
{
|
||||
pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)];
|
||||
size = r->DataLength;
|
||||
}
|
||||
#elif CFG_TUD_NET == OPT_NET_EEM
|
||||
struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt;
|
||||
|
||||
(void)len;
|
||||
|
||||
if (hdr->bmType)
|
||||
if (_netd_itf.ecm_mode)
|
||||
{
|
||||
/* EEM Control Packet: discard it */
|
||||
tud_network_recv_renew();
|
||||
size = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* EEM Data Packet */
|
||||
pnt += CFG_TUD_NET_PACKET_PREFIX_LEN;
|
||||
size = hdr->length - 4; /* discard the unused CRC-32 */
|
||||
rndis_data_packet_t *r = (rndis_data_packet_t *)pnt;
|
||||
if (len >= sizeof(rndis_data_packet_t))
|
||||
if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len))
|
||||
if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len)
|
||||
{
|
||||
pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)];
|
||||
size = r->DataLength;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool accepted = false;
|
||||
|
||||
if (size)
|
||||
{
|
||||
struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);
|
||||
bool accepted = true;
|
||||
|
||||
if (p)
|
||||
{
|
||||
memcpy(p->payload, pnt, size);
|
||||
p->len = size;
|
||||
accepted = tud_network_recv_cb(p);
|
||||
}
|
||||
|
||||
if (!p || !accepted)
|
||||
{
|
||||
/* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */
|
||||
tud_network_recv_renew();
|
||||
if (!accepted) pbuf_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (!accepted)
|
||||
{
|
||||
/* if a buffer was never handled by user code, we must renew on the user's behalf */
|
||||
tud_network_recv_renew();
|
||||
}
|
||||
}
|
||||
|
||||
bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
|
||||
@@ -320,6 +414,11 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
}
|
||||
}
|
||||
|
||||
if ( _netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif) )
|
||||
{
|
||||
if (sizeof(notify.ecm_buf.header) == xferred_bytes) ecm_report(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -337,7 +436,7 @@ void tud_network_xmit(struct pbuf *p)
|
||||
if (!can_xmit)
|
||||
return;
|
||||
|
||||
len = CFG_TUD_NET_PACKET_PREFIX_LEN;
|
||||
len = (_netd_itf.ecm_mode) ? 0 : CFG_TUD_NET_PACKET_PREFIX_LEN;
|
||||
data = transmitted + len;
|
||||
|
||||
for(q = p; q != NULL; q = q->next)
|
||||
@@ -347,23 +446,15 @@ void tud_network_xmit(struct pbuf *p)
|
||||
len += q->len;
|
||||
}
|
||||
|
||||
#if CFG_TUD_NET == OPT_NET_RNDIS
|
||||
rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted;
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = len;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset);
|
||||
hdr->DataLength = len - sizeof(rndis_data_packet_t);
|
||||
#elif CFG_TUD_NET == OPT_NET_EEM
|
||||
struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted;
|
||||
/* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */
|
||||
data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF;
|
||||
/* adjust length to reflect added fake CRC-32 */
|
||||
len += 4;
|
||||
hdr->bmType = 0; /* EEM Data Packet */
|
||||
hdr->length = len - sizeof(struct cdc_eem_packet_header);
|
||||
hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */
|
||||
#endif
|
||||
if (!_netd_itf.ecm_mode)
|
||||
{
|
||||
rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted;
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = len;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset);
|
||||
hdr->DataLength = len - sizeof(rndis_data_packet_t);
|
||||
}
|
||||
|
||||
do_in_xfer(transmitted, len);
|
||||
}
|
||||
|
||||
@@ -263,17 +263,19 @@ void usbtmcd_init_cb(void)
|
||||
bool usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
|
||||
{
|
||||
(void)rhport;
|
||||
TU_ASSERT(usbtmc_state.state == STATE_CLOSED);
|
||||
uint8_t const * p_desc;
|
||||
uint8_t found_endpoints = 0;
|
||||
|
||||
TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS);
|
||||
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS);
|
||||
|
||||
#ifndef NDEBUG
|
||||
TU_ASSERT(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS);
|
||||
TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS);
|
||||
// Only 2 or 3 endpoints are allowed for USBTMC.
|
||||
TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3));
|
||||
#endif
|
||||
|
||||
TU_ASSERT(usbtmc_state.state == STATE_CLOSED);
|
||||
|
||||
// Interface
|
||||
(*p_length) = 0u;
|
||||
p_desc = (uint8_t const *) itf_desc;
|
||||
|
||||
Vendored
+2
@@ -168,6 +168,8 @@ void vendord_reset(uint8_t rhport)
|
||||
|
||||
bool vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len)
|
||||
{
|
||||
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass);
|
||||
|
||||
// Find available interface
|
||||
vendord_interface_t* p_vendor = NULL;
|
||||
for(uint8_t i=0; i<CFG_TUD_VENDOR; i++)
|
||||
|
||||
@@ -139,6 +139,7 @@ typedef enum
|
||||
TUSB_REQ_RCPT_OTHER
|
||||
} tusb_request_recipient_t;
|
||||
|
||||
// https://www.usb.org/defined-class-codes
|
||||
typedef enum
|
||||
{
|
||||
TUSB_CLASS_UNSPECIFIED = 0 ,
|
||||
@@ -176,6 +177,12 @@ typedef enum
|
||||
MISC_PROTOCOL_IAD = 1
|
||||
}misc_protocol_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
APP_SUBCLASS_USBTMC = 0x03,
|
||||
APP_SUBCLASS_DFU_RUNTIME = 0x01
|
||||
} app_subclass_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DEVICE_CAPABILITY_WIRELESS_USB = 0x01,
|
||||
|
||||
+8
-4
@@ -89,7 +89,7 @@ typedef struct TU_ATTR_ALIGNED(4)
|
||||
void dcd_init (uint8_t rhport);
|
||||
|
||||
// Interrupt Handler
|
||||
void dcd_irq_handler(uint8_t rhport) TU_ATTR_USED;
|
||||
void dcd_int_handler(uint8_t rhport);
|
||||
|
||||
// Enable device interrupt
|
||||
void dcd_int_enable (uint8_t rhport);
|
||||
@@ -106,10 +106,10 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num);
|
||||
// Wake up host
|
||||
void dcd_remote_wakeup(uint8_t rhport);
|
||||
|
||||
// Connect or disconnect D+/D- line pull-up resistor.
|
||||
// Defined in dcd source if MCU has internal pull-up.
|
||||
// Otherwise, may be defined in BSP.
|
||||
// Connect by enabling internal pull-up resistor on D+/D-
|
||||
void dcd_connect(uint8_t rhport) TU_ATTR_WEAK;
|
||||
|
||||
// Disconnect by disabling internal pull-up resistor on D+/D-
|
||||
void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -123,6 +123,10 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re
|
||||
// Configure endpoint's registers according to descriptor
|
||||
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
|
||||
|
||||
// Close an endpoint.
|
||||
// Since it is weak, caller must TU_ASSERT this function's existence before calling it.
|
||||
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK;
|
||||
|
||||
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
|
||||
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
|
||||
|
||||
|
||||
+98
-108
@@ -73,8 +73,17 @@ enum { DRVID_INVALID = 0xFFu };
|
||||
//--------------------------------------------------------------------+
|
||||
// Class Driver
|
||||
//--------------------------------------------------------------------+
|
||||
typedef struct {
|
||||
uint8_t class_code;
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
#define DRIVER_NAME(_name) .name = _name,
|
||||
#else
|
||||
#define DRIVER_NAME(_name)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
char const* name;
|
||||
#endif
|
||||
|
||||
void (* init ) (void);
|
||||
void (* reset ) (uint8_t rhport);
|
||||
@@ -89,7 +98,7 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
{
|
||||
#if CFG_TUD_CDC
|
||||
{
|
||||
.class_code = TUSB_CLASS_CDC,
|
||||
DRIVER_NAME("CDC")
|
||||
.init = cdcd_init,
|
||||
.reset = cdcd_reset,
|
||||
.open = cdcd_open,
|
||||
@@ -102,7 +111,7 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
|
||||
#if CFG_TUD_MSC
|
||||
{
|
||||
.class_code = TUSB_CLASS_MSC,
|
||||
DRIVER_NAME("MSC")
|
||||
.init = mscd_init,
|
||||
.reset = mscd_reset,
|
||||
.open = mscd_open,
|
||||
@@ -115,7 +124,7 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
|
||||
#if CFG_TUD_HID
|
||||
{
|
||||
.class_code = TUSB_CLASS_HID,
|
||||
DRIVER_NAME("HID")
|
||||
.init = hidd_init,
|
||||
.reset = hidd_reset,
|
||||
.open = hidd_open,
|
||||
@@ -128,7 +137,7 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
|
||||
#if CFG_TUD_MIDI
|
||||
{
|
||||
.class_code = TUSB_CLASS_AUDIO,
|
||||
DRIVER_NAME("MIDI")
|
||||
.init = midid_init,
|
||||
.open = midid_open,
|
||||
.reset = midid_reset,
|
||||
@@ -141,7 +150,7 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
|
||||
#if CFG_TUD_VENDOR
|
||||
{
|
||||
.class_code = TUSB_CLASS_VENDOR_SPECIFIC,
|
||||
DRIVER_NAME("VENDOR")
|
||||
.init = vendord_init,
|
||||
.reset = vendord_reset,
|
||||
.open = vendord_open,
|
||||
@@ -153,12 +162,8 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_USBTMC
|
||||
// Presently USBTMC is the only defined class with the APP_SPECIFIC class code.
|
||||
// We maybe need to add subclass codes here, or a callback to ask if a driver can
|
||||
// handle a particular interface.
|
||||
{
|
||||
.class_code = TUD_USBTMC_APP_CLASS,
|
||||
//.subclass_code = TUD_USBTMC_APP_SUBCLASS
|
||||
DRIVER_NAME("TMC")
|
||||
.init = usbtmcd_init_cb,
|
||||
.reset = usbtmcd_reset_cb,
|
||||
.open = usbtmcd_open_cb,
|
||||
@@ -171,8 +176,7 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
|
||||
#if CFG_TUD_DFU_RT
|
||||
{
|
||||
.class_code = TUD_DFU_APP_CLASS,
|
||||
//.subclass_code = TUD_DFU_APP_SUBCLASS
|
||||
DRIVER_NAME("DFU-RT")
|
||||
.init = dfu_rtd_init,
|
||||
.reset = dfu_rtd_reset,
|
||||
.open = dfu_rtd_open,
|
||||
@@ -185,19 +189,14 @@ static usbd_class_driver_t const _usbd_driver[] =
|
||||
|
||||
#if CFG_TUD_NET
|
||||
{
|
||||
.class_code =
|
||||
#if CFG_TUD_NET == OPT_NET_RNDIS
|
||||
TUD_RNDIS_ITF_CLASS,
|
||||
#else
|
||||
TUSB_CLASS_CDC,
|
||||
#endif
|
||||
DRIVER_NAME("NET")
|
||||
.init = netd_init,
|
||||
.reset = netd_reset,
|
||||
.open = netd_open,
|
||||
.control_request = netd_control_request,
|
||||
.control_complete = netd_control_complete,
|
||||
.xfer_cb = netd_xfer_cb,
|
||||
.sof = NULL
|
||||
.sof = NULL,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
@@ -244,32 +243,6 @@ static char const* const _usbd_event_str[DCD_EVENT_COUNT] =
|
||||
"FUNC_CALL"
|
||||
};
|
||||
|
||||
// must be same driver order as usbd_class_drivers[]
|
||||
static char const* const _usbd_driver_str[USBD_CLASS_DRIVER_COUNT] =
|
||||
{
|
||||
#if CFG_TUD_CDC
|
||||
"CDC",
|
||||
#endif
|
||||
#if CFG_TUD_MSC
|
||||
"MSC",
|
||||
#endif
|
||||
#if CFG_TUD_HID
|
||||
"HID",
|
||||
#endif
|
||||
#if CFG_TUD_MIDI
|
||||
"MIDI",
|
||||
#endif
|
||||
#if CFG_TUD_VENDOR
|
||||
"Vendor",
|
||||
#endif
|
||||
#if CFG_TUD_USBTMC
|
||||
"USBTMC"
|
||||
#endif
|
||||
#if CFG_TUD_NET
|
||||
"NET"
|
||||
#endif
|
||||
};
|
||||
|
||||
static char const* const _tusb_std_request_str[] =
|
||||
{
|
||||
"Get Status" ,
|
||||
@@ -326,7 +299,7 @@ bool tud_init (void)
|
||||
// Init class drivers
|
||||
for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++)
|
||||
{
|
||||
TU_LOG2("%s init\r\n", _usbd_driver_str[i]);
|
||||
TU_LOG2("%s init\r\n", _usbd_driver[i].name);
|
||||
_usbd_driver[i].init();
|
||||
}
|
||||
|
||||
@@ -435,7 +408,7 @@ void tud_task (void)
|
||||
uint8_t const drv_id = _usbd_dev.ep2drv[epnum][ep_dir];
|
||||
TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,);
|
||||
|
||||
TU_LOG2(" %s xfer callback\r\n", _usbd_driver_str[drv_id]);
|
||||
TU_LOG2(" %s xfer callback\r\n", _usbd_driver[drv_id].name);
|
||||
_usbd_driver[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
|
||||
}
|
||||
}
|
||||
@@ -480,7 +453,7 @@ static bool invoke_class_control(uint8_t rhport, uint8_t drvid, tusb_control_req
|
||||
TU_ASSERT(_usbd_driver[drvid].control_request);
|
||||
|
||||
usbd_control_set_complete_callback(_usbd_driver[drvid].control_complete);
|
||||
TU_LOG2(" %s control request\r\n", _usbd_driver_str[drvid]);
|
||||
TU_LOG2(" %s control request\r\n", _usbd_driver[drvid].name);
|
||||
return _usbd_driver[drvid].control_request(rhport, request);
|
||||
}
|
||||
|
||||
@@ -596,38 +569,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
|
||||
uint8_t const drvid = _usbd_dev.itf2drv[itf];
|
||||
TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT);
|
||||
|
||||
if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD)
|
||||
// all requests to Interface (STD or Class) is forwarded to class driver.
|
||||
// notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE
|
||||
if ( !invoke_class_control(rhport, drvid, p_request) )
|
||||
{
|
||||
switch ( p_request->bRequest )
|
||||
{
|
||||
case TUSB_REQ_GET_INTERFACE:
|
||||
{
|
||||
// TODO not support alternate interface yet
|
||||
uint8_t alternate = 0;
|
||||
tud_control_xfer(rhport, p_request, &alternate, 1);
|
||||
}
|
||||
break;
|
||||
// For GET_INTERFACE, it is mandatory to respond even if the class
|
||||
// driver doesn't use alternate settings.
|
||||
TU_VERIFY( TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type &&
|
||||
TUSB_REQ_GET_INTERFACE == p_request->bRequest);
|
||||
|
||||
case TUSB_REQ_SET_INTERFACE:
|
||||
{
|
||||
uint8_t const alternate = (uint8_t) p_request->wValue;
|
||||
|
||||
// TODO not support alternate interface yet
|
||||
TU_ASSERT(alternate == 0);
|
||||
tud_control_status(rhport, p_request);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// forward to class driver: "STD request to Interface"
|
||||
// GET HID REPORT DESCRIPTOR falls into this case
|
||||
TU_VERIFY(invoke_class_control(rhport, drvid, p_request));
|
||||
break;
|
||||
}
|
||||
}else
|
||||
{
|
||||
// forward to class driver: "non-STD request to Interface"
|
||||
TU_VERIFY(invoke_class_control(rhport, drvid, p_request));
|
||||
uint8_t alternate = 0;
|
||||
tud_control_xfer(rhport, p_request, &alternate, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -727,37 +679,59 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
|
||||
|
||||
while( p_desc < desc_end )
|
||||
{
|
||||
// Each interface always starts with Interface or Association descriptor
|
||||
tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL;
|
||||
|
||||
// Class will always starts with Interface Association (if any) and then Interface descriptor
|
||||
if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
|
||||
{
|
||||
p_desc = tu_desc_next(p_desc); // ignore Interface Association
|
||||
}else
|
||||
{
|
||||
TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) );
|
||||
|
||||
tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc;
|
||||
|
||||
// Check if class is supported
|
||||
uint8_t drv_id;
|
||||
for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++)
|
||||
{
|
||||
if ( _usbd_driver[drv_id].class_code == desc_itf->bInterfaceClass ) break;
|
||||
}
|
||||
TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT );
|
||||
|
||||
// Interface number must not be used already TODO alternate interface
|
||||
TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] );
|
||||
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id;
|
||||
|
||||
uint16_t itf_len=0;
|
||||
TU_LOG2(" %s open\r\n", _usbd_driver_str[drv_id]);
|
||||
TU_ASSERT( _usbd_driver[drv_id].open(rhport, desc_itf, &itf_len) );
|
||||
TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) );
|
||||
|
||||
mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id);
|
||||
|
||||
p_desc += itf_len; // next interface
|
||||
desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc;
|
||||
p_desc = tu_desc_next(p_desc); // next to Interface
|
||||
}
|
||||
|
||||
TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) );
|
||||
|
||||
tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc;
|
||||
uint8_t drv_id;
|
||||
uint16_t drv_len;
|
||||
|
||||
for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++)
|
||||
{
|
||||
usbd_class_driver_t const *driver = &_usbd_driver[drv_id];
|
||||
|
||||
drv_len = 0;
|
||||
if ( driver->open(rhport, desc_itf, &drv_len) )
|
||||
{
|
||||
// Interface number must not be used already
|
||||
TU_ASSERT( DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] );
|
||||
|
||||
TU_LOG2(" %s open\r\n", _usbd_driver[drv_id].name);
|
||||
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id;
|
||||
|
||||
// If IAD exist, assign all interfaces to the same driver
|
||||
if (desc_itf_assoc)
|
||||
{
|
||||
// IAD's first interface number and class/subclass/protocol should match with opened interface
|
||||
TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber &&
|
||||
desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass &&
|
||||
desc_itf_assoc->bFunctionSubClass == desc_itf->bInterfaceSubClass &&
|
||||
desc_itf_assoc->bFunctionProtocol == desc_itf->bInterfaceProtocol);
|
||||
|
||||
for(uint8_t i=1; i<desc_itf_assoc->bInterfaceCount; i++)
|
||||
{
|
||||
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Assert if cannot find supported driver
|
||||
TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT && drv_len >= sizeof(tusb_desc_interface_t) );
|
||||
|
||||
mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor
|
||||
|
||||
p_desc += drv_len; // next interface
|
||||
}
|
||||
|
||||
// invoke callback
|
||||
@@ -1035,4 +1009,20 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr)
|
||||
return _usbd_dev.ep_status[epnum][dir].stalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* usbd_edpt_close will disable an endpoint.
|
||||
*
|
||||
* In progress transfers on this EP may be delivered after this call.
|
||||
*
|
||||
*/
|
||||
void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
TU_ASSERT(dcd_edpt_close, /**/);
|
||||
TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr);
|
||||
|
||||
dcd_edpt_close(rhport, ep_addr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+19
-31
@@ -48,7 +48,7 @@ bool tud_init (void);
|
||||
void tud_task (void);
|
||||
|
||||
// Interrupt handler, name alias to DCD
|
||||
#define tud_irq_handler dcd_irq_handler
|
||||
#define tud_int_handler dcd_int_handler
|
||||
|
||||
// Check if device is connected and configured
|
||||
bool tud_mounted(void);
|
||||
@@ -183,9 +183,9 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
#define TUD_CDC_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \
|
||||
/* Interface Associate */\
|
||||
8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, 0,\
|
||||
8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\
|
||||
/* CDC Control Interface */\
|
||||
9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, _stridx,\
|
||||
9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\
|
||||
/* CDC Header */\
|
||||
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\
|
||||
/* CDC Call */\
|
||||
@@ -291,23 +291,23 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
|
||||
// Interface number, number of endpoints, EP string index, USB_TMC_PROTOCOL*, bulk-out endpoint ID,
|
||||
// bulk-in endpoint ID
|
||||
#define TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, _stridx, _itfProtocol) \
|
||||
/* Interface */ \
|
||||
/* Interface */ \
|
||||
0x09, TUSB_DESC_INTERFACE, _itfnum, 0x00, _bNumEndpoints, TUD_USBTMC_APP_CLASS, TUD_USBTMC_APP_SUBCLASS, _itfProtocol, _stridx
|
||||
|
||||
#define TUD_USBTMC_IF_DESCRIPTOR_LEN 9u
|
||||
|
||||
#define TUD_USBTMC_BULK_DESCRIPTORS(_epout, _epin, _bulk_epsize) \
|
||||
/* Endpoint Out */ \
|
||||
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \
|
||||
/* Endpoint In */ \
|
||||
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u
|
||||
/* Endpoint Out */ \
|
||||
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u, \
|
||||
/* Endpoint In */ \
|
||||
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_epsize), 0u
|
||||
|
||||
#define TUD_USBTMC_BULK_DESCRIPTORS_LEN (7u+7u)
|
||||
|
||||
/* optional interrupt endpoint */ \
|
||||
// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number?
|
||||
#define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \
|
||||
7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16
|
||||
7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16
|
||||
|
||||
#define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u)
|
||||
|
||||
@@ -342,12 +342,14 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
|
||||
|
||||
//------------- CDC-ECM -------------//
|
||||
|
||||
// Length of template descriptor: 62 bytes
|
||||
#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+7+7)
|
||||
// Length of template descriptor: 71 bytes
|
||||
#define TUD_CDC_ECM_DESC_LEN (8+9+5+5+13+7+9+9+7+7)
|
||||
|
||||
// CDC-ECM Descriptor Template
|
||||
// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
|
||||
#define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \
|
||||
/* Interface Association */\
|
||||
8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, 0,\
|
||||
/* CDC Control Interface */\
|
||||
9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\
|
||||
/* CDC-ECM Header */\
|
||||
@@ -358,8 +360,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
|
||||
13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\
|
||||
/* Endpoint Notification */\
|
||||
7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\
|
||||
/* CDC Data Interface */\
|
||||
9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
|
||||
/* CDC Data Interface (default inactive) */\
|
||||
9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 0, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
|
||||
/* CDC Data Interface (alternative active) */\
|
||||
9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 1, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
|
||||
/* Endpoint In */\
|
||||
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
|
||||
/* Endpoint Out */\
|
||||
@@ -372,10 +376,10 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
|
||||
/* Windows XP */
|
||||
#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC
|
||||
#define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
|
||||
#define TUD_RNDIS_ITF_PROTOCOL CDC_COMM_PROTOCOL_MICROSOFT_RNDIS
|
||||
#define TUD_RNDIS_ITF_PROTOCOL 0xFF /* CDC_COMM_PROTOCOL_MICROSOFT_RNDIS */
|
||||
#else
|
||||
/* Windows 7+ */
|
||||
#define TUD_RNDIS_ITF_CLASS 0xE0
|
||||
#define TUD_RNDIS_ITF_CLASS TUSB_CLASS_WIRELESS_CONTROLLER
|
||||
#define TUD_RNDIS_ITF_SUBCLASS 0x01
|
||||
#define TUD_RNDIS_ITF_PROTOCOL 0x03
|
||||
#endif
|
||||
@@ -408,22 +412,6 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
|
||||
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
|
||||
|
||||
|
||||
//------------- CDC-EEM -------------//
|
||||
|
||||
// Length of template descriptor: 23 bytes
|
||||
#define TUD_CDC_EEM_DESC_LEN (9+7+7)
|
||||
|
||||
// CDC-EEM Descriptor Template
|
||||
// Interface number, description string index, EP data address (out, in) and size.
|
||||
#define TUD_CDC_EEM_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \
|
||||
/* EEM Interface */\
|
||||
9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL, CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL, _stridx,\
|
||||
/* Endpoint In */\
|
||||
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
|
||||
/* Endpoint Out */\
|
||||
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
//bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
|
||||
void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
// Submit a usb transfer
|
||||
bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
|
||||
|
||||
@@ -190,9 +190,6 @@ void dcd_init(uint8_t rhport)
|
||||
USB_ENUMDONEMSK_M |
|
||||
USB_RESETDETMSK_M |
|
||||
USB_DISCONNINTMSK_M;
|
||||
|
||||
ESP_LOGV(TAG, "DCD init - Soft CONNECT");
|
||||
USB0.dctl &= ~USB_SFTDISCON_M; // Connect
|
||||
}
|
||||
|
||||
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
|
||||
@@ -216,18 +213,20 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
(void)rhport;
|
||||
}
|
||||
|
||||
// disconnect by disabling internal pull-up resistor on D+/D-
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
USB0.dctl |= USB_SFTDISCON_M;
|
||||
}
|
||||
|
||||
// connect by enabling internal pull-up resistor on D+/D-
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
USB0.dctl &= ~USB_SFTDISCON_M;
|
||||
}
|
||||
|
||||
// disconnect by disabling internal pull-up resistor on D+/D-
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
USB0.dctl |= USB_SFTDISCON_M;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* DCD Endpoint port
|
||||
*------------------------------------------------------------------*/
|
||||
@@ -639,7 +638,7 @@ static void handle_epin_ints(void)
|
||||
}
|
||||
|
||||
|
||||
static void dcd_int_handler(void* arg)
|
||||
static void _dcd_int_handler(void* arg)
|
||||
{
|
||||
(void) arg;
|
||||
|
||||
@@ -727,7 +726,7 @@ static void dcd_int_handler(void* arg)
|
||||
void dcd_int_enable (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) dcd_int_handler, NULL, &usb_ih);
|
||||
esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih);
|
||||
}
|
||||
|
||||
void dcd_int_disable (uint8_t rhport)
|
||||
|
||||
@@ -331,7 +331,7 @@ void maybe_transfer_complete(void) {
|
||||
}
|
||||
|
||||
|
||||
void dcd_irq_handler (uint8_t rhport)
|
||||
void dcd_int_handler (uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
|
||||
@@ -138,9 +138,6 @@ void dcd_init (uint8_t rhport)
|
||||
(void) rhport;
|
||||
|
||||
tu_memclr(_dcd_xfer, sizeof(_dcd_xfer));
|
||||
|
||||
// Enable pull-up, disable transceiver
|
||||
UDP->UDP_TXVC = UDP_TXVC_PUON | UDP_TXVC_TXVDIS_Msk;
|
||||
}
|
||||
|
||||
// Enable device interrupt
|
||||
@@ -186,6 +183,23 @@ void dcd_remote_wakeup (uint8_t rhport)
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// Enable pull-up, disable transceiver
|
||||
UDP->UDP_TXVC = UDP_TXVC_PUON | UDP_TXVC_TXVDIS_Msk;
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// disable both pullup and transceiver
|
||||
UDP->UDP_TXVC = UDP_TXVC_TXVDIS_Msk;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -333,7 +347,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
||||
//--------------------------------------------------------------------+
|
||||
// ISR
|
||||
//--------------------------------------------------------------------+
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
uint32_t const intr_mask = UDP->UDP_IMR;
|
||||
uint32_t const intr_status = UDP->UDP_ISR & intr_mask;
|
||||
|
||||
@@ -373,7 +373,7 @@ void bus_reset(void)
|
||||
_dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE;
|
||||
}
|
||||
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
ep->CFG |= USBD_CFG_CSTALL_Msk;
|
||||
}
|
||||
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
|
||||
@@ -312,7 +312,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
ep->CFG |= USBD_CFG_CSTALL_Msk;
|
||||
}
|
||||
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
|
||||
@@ -112,8 +112,6 @@ static struct
|
||||
uint16_t total_bytes;
|
||||
} ctrl_in_xfer;
|
||||
|
||||
static volatile bool configuration_changed;
|
||||
|
||||
static volatile struct xfer_ctl_t *current_dma_xfer;
|
||||
|
||||
|
||||
@@ -219,7 +217,6 @@ static void bus_reset(void)
|
||||
/* Reset USB device address */
|
||||
USBD->FADDR = 0;
|
||||
|
||||
configuration_changed = false;
|
||||
current_dma_xfer = NULL;
|
||||
}
|
||||
|
||||
@@ -305,7 +302,6 @@ void dcd_set_config(uint8_t rhport, uint8_t config_num)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) config_num;
|
||||
configuration_changed = true;
|
||||
}
|
||||
|
||||
void dcd_remote_wakeup(uint8_t rhport)
|
||||
@@ -435,7 +431,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
}
|
||||
}
|
||||
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
@@ -579,15 +575,14 @@ void dcd_irq_handler(uint8_t rhport)
|
||||
else if (cep_state & USBD_CEPINTSTS_STSDONEIF_Msk)
|
||||
{
|
||||
/* given ACK from host has happened, we can now set the address (if not already done) */
|
||||
if((USBD->FADDR != assigned_address) && (USBD->FADDR == 0)) USBD->FADDR = assigned_address;
|
||||
|
||||
if (configuration_changed)
|
||||
if((USBD->FADDR != assigned_address) && (USBD->FADDR == 0))
|
||||
{
|
||||
USBD->FADDR = assigned_address;
|
||||
|
||||
for (enum ep_enum ep_index = PERIPH_EPA; ep_index < PERIPH_MAX_EP; ep_index++)
|
||||
{
|
||||
if (USBD->EP[ep_index].EPCFG & USBD_EPCFG_EPEN_Msk) USBD->EP[ep_index].EPRSPCTL = USBD_EPRSPCTL_TOGGLE_Msk;
|
||||
}
|
||||
configuration_changed = false;
|
||||
}
|
||||
|
||||
USBD->CEPINTEN = USBD_CEPINTEN_SETUPPKIEN_Msk;
|
||||
|
||||
@@ -181,9 +181,7 @@ void dcd_init(uint8_t rhport)
|
||||
LPC_USB->UDCAH = (uint32_t) _dcd.udca;
|
||||
LPC_USB->DMAIntEn = (DMA_INT_END_OF_XFER_MASK /*| DMA_INT_NEW_DD_REQUEST_MASK*/ | DMA_INT_ERROR_MASK);
|
||||
|
||||
sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); // connect
|
||||
|
||||
// USB IRQ priority should be set by application previously
|
||||
// Clear pending IRQ
|
||||
NVIC_ClearPendingIRQ(USB_IRQn);
|
||||
}
|
||||
|
||||
@@ -221,6 +219,18 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, SIE_DEV_STATUS_CONNECT_STATUS_MASK);
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// CONTROL HELPER
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -498,7 +508,7 @@ static void dd_complete_isr(uint8_t rhport, uint8_t ep_id)
|
||||
}
|
||||
|
||||
// main USB IRQ handler
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
uint32_t const dev_int_status = LPC_USB->DevIntSt & LPC_USB->DevIntEn;
|
||||
LPC_USB->DevIntClr = dev_int_status;// Acknowledge handled interrupt
|
||||
|
||||
@@ -95,7 +95,7 @@ enum {
|
||||
CMDSTAT_DEVICE_ADDR_MASK = TU_BIT(7 )-1,
|
||||
CMDSTAT_DEVICE_ENABLE_MASK = TU_BIT(7 ),
|
||||
CMDSTAT_SETUP_RECEIVED_MASK = TU_BIT(8 ),
|
||||
CMDSTAT_DEVICE_CONNECT_MASK = TU_BIT(16), ///< reflect the softconnect only, does not reflect the actual attached state
|
||||
CMDSTAT_DEVICE_CONNECT_MASK = TU_BIT(16), ///< reflect the soft-connect only, does not reflect the actual attached state
|
||||
CMDSTAT_DEVICE_SUSPEND_MASK = TU_BIT(17),
|
||||
CMDSTAT_CONNECT_CHANGE_MASK = TU_BIT(24),
|
||||
CMDSTAT_SUSPEND_CHANGE_MASK = TU_BIT(25),
|
||||
@@ -209,6 +209,18 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
DCD_REGS->DEVCMDSTAT |= CMDSTAT_DEVICE_CONNECT_MASK;
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
DCD_REGS->DEVCMDSTAT &= ~CMDSTAT_DEVICE_CONNECT_MASK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// DCD Endpoint Port
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -333,7 +345,7 @@ static void process_xfer_isr(uint32_t int_status)
|
||||
}
|
||||
}
|
||||
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
(void) rhport; // TODO support multiple USB on supported mcu such as LPC55s69
|
||||
|
||||
|
||||
@@ -322,7 +322,7 @@ void dcd_init(uint8_t rhport)
|
||||
{
|
||||
tu_memclr(&_dcd_data, sizeof(dcd_data_t));
|
||||
|
||||
dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs;
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
|
||||
// Reset controller
|
||||
dcd_reg->USBCMD |= USBCMD_RESET;
|
||||
@@ -342,7 +342,6 @@ void dcd_init(uint8_t rhport)
|
||||
dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_RESET | INTR_SUSPEND /*| INTR_SOF*/;
|
||||
|
||||
dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0
|
||||
dcd_reg->USBCMD |= TU_BIT(0); // connect
|
||||
}
|
||||
|
||||
void dcd_int_enable(uint8_t rhport)
|
||||
@@ -376,6 +375,18 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
dcd_reg->USBCMD |= USBCMD_RUN_STOP;
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
|
||||
dcd_reg->USBCMD &= ~USBCMD_RUN_STOP;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HELPER
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -492,7 +503,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
|
||||
//--------------------------------------------------------------------+
|
||||
// ISR
|
||||
//--------------------------------------------------------------------+
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs;
|
||||
|
||||
|
||||
@@ -201,6 +201,18 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
DEV_WAKEUP(usbdev);
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
DEV_CONNECT(usbdev);
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
DEV_DISCONNECT(usbdev);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@@ -63,19 +63,16 @@
|
||||
* Current driver limitations (i.e., a list of features for you to add):
|
||||
* - STALL handled, but not tested.
|
||||
* - Does it work? No clue.
|
||||
* - All EP BTABLE buffers are created as max 64 bytes.
|
||||
* - Smaller can be requested, but it has to be an even number.
|
||||
* - All EP BTABLE buffers are created based on max packet size of first EP opened with that address.
|
||||
* - No isochronous endpoints
|
||||
* - Endpoint index is the ID of the endpoint
|
||||
* - This means that priority is given to endpoints with lower ID numbers
|
||||
* - Code is mixing up EP IX with EP ID. Everywhere.
|
||||
* - No way to close endpoints; Can a device be reconfigured without a reset?
|
||||
* - Packet buffer memory is copied in the interrupt.
|
||||
* - This is better for performance, but means interrupts are disabled for longer
|
||||
* - DMA may be the best choice, but it could also be pushed to the USBD task.
|
||||
* - No double-buffering
|
||||
* - No DMA
|
||||
* - No provision to control the D+ pull-up using GPIO on devices without an internal pull-up.
|
||||
* - Minimal error handling
|
||||
* - Perhaps error interrupts should be reported to the stack, or cause a device reset?
|
||||
* - Assumes a single USB peripheral; I think that no hardware has multiple so this is fine.
|
||||
@@ -131,15 +128,16 @@
|
||||
* Configuration
|
||||
*****************************************************/
|
||||
|
||||
// HW supports max of 8 endpoints, but this can be reduced to save RAM
|
||||
// HW supports max of 8 bidirectional endpoints, but this can be reduced to save RAM
|
||||
// (8u here would mean 8 IN and 8 OUT)
|
||||
#ifndef MAX_EP_COUNT
|
||||
# define MAX_EP_COUNT 8u
|
||||
# define MAX_EP_COUNT 8U
|
||||
#endif
|
||||
|
||||
// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it
|
||||
// Both of these MUST be a multiple of 2, and are in byte units.
|
||||
#ifndef DCD_STM32_BTABLE_BASE
|
||||
# define DCD_STM32_BTABLE_BASE 0u
|
||||
# define DCD_STM32_BTABLE_BASE 0U
|
||||
#endif
|
||||
|
||||
#ifndef DCD_STM32_BTABLE_LENGTH
|
||||
@@ -163,7 +161,9 @@ typedef struct
|
||||
uint8_t * buffer;
|
||||
uint16_t total_len;
|
||||
uint16_t queued_len;
|
||||
uint16_t max_packet_size;
|
||||
uint16_t pma_ptr;
|
||||
uint8_t max_packet_size;
|
||||
uint8_t pma_alloc_size;
|
||||
} xfer_ctl_t;
|
||||
|
||||
static xfer_ctl_t xfer_status[MAX_EP_COUNT][2];
|
||||
@@ -177,15 +177,19 @@ static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6];
|
||||
|
||||
static uint8_t remoteWakeCountdown; // When wake is requested
|
||||
|
||||
// EP Buffers assigned from end of memory location, to minimize their chance of crashing
|
||||
// into the stack.
|
||||
static uint16_t ep_buf_ptr;
|
||||
static void dcd_handle_bus_reset(void);
|
||||
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes);
|
||||
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes);
|
||||
static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix);
|
||||
static void dcd_ep_ctr_handler(void);
|
||||
|
||||
// PMA allocation/access
|
||||
static uint8_t open_ep_count;
|
||||
static uint16_t ep_buf_ptr; ///< Points to first free memory location
|
||||
static void dcd_pma_alloc_reset(void);
|
||||
static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length);
|
||||
static void dcd_pma_free(uint8_t ep_addr);
|
||||
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes);
|
||||
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes);
|
||||
|
||||
// Using a function due to better type checks
|
||||
// This seems better than having to do type casts everywhere else
|
||||
@@ -219,7 +223,7 @@ void dcd_init (uint8_t rhport)
|
||||
asm("NOP");
|
||||
}
|
||||
USB->CNTR = 0; // Enable USB
|
||||
|
||||
|
||||
USB->BTABLE = DCD_STM32_BTABLE_BASE;
|
||||
|
||||
reg16_clear_bits(&USB->ISTR, USB_ISTR_ALL_EVENTS); // Clear pending interrupts
|
||||
@@ -231,12 +235,6 @@ void dcd_init (uint8_t rhport)
|
||||
pcd_set_endpoint(USB,i,0u);
|
||||
}
|
||||
|
||||
// Initialize the BTABLE for EP0 at this point (though setting up the EP0R is unneeded)
|
||||
// This is actually not necessary, but helps debugging to start with a blank RAM area
|
||||
for(uint32_t i=0;i<(DCD_STM32_BTABLE_LENGTH>>1); i++)
|
||||
{
|
||||
pma[PMA_STRIDE*(DCD_STM32_BTABLE_BASE + i)] = 0u;
|
||||
}
|
||||
USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
|
||||
dcd_handle_bus_reset();
|
||||
|
||||
@@ -368,7 +366,7 @@ static void dcd_handle_bus_reset(void)
|
||||
pcd_set_endpoint(USB,i,0u);
|
||||
}
|
||||
|
||||
ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each)
|
||||
dcd_pma_alloc_reset();
|
||||
dcd_edpt_open (0, &ep0OUT_desc);
|
||||
dcd_edpt_open (0, &ep0IN_desc);
|
||||
|
||||
@@ -501,7 +499,7 @@ static void dcd_ep_ctr_handler(void)
|
||||
}
|
||||
}
|
||||
|
||||
void dcd_irq_handler(uint8_t rhport) {
|
||||
void dcd_int_handler(uint8_t rhport) {
|
||||
|
||||
(void) rhport;
|
||||
|
||||
@@ -592,6 +590,85 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re
|
||||
}
|
||||
}
|
||||
|
||||
static void dcd_pma_alloc_reset(void)
|
||||
{
|
||||
ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each)
|
||||
//TU_LOG2("dcd_pma_alloc_reset()\r\n");
|
||||
for(uint32_t i=0; i<MAX_EP_COUNT; i++)
|
||||
{
|
||||
xfer_ctl_ptr(i,TUSB_DIR_OUT)->pma_alloc_size = 0U;
|
||||
xfer_ctl_ptr(i,TUSB_DIR_IN)->pma_alloc_size = 0U;
|
||||
xfer_ctl_ptr(i,TUSB_DIR_OUT)->pma_ptr = 0U;
|
||||
xfer_ctl_ptr(i,TUSB_DIR_IN)->pma_ptr = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Allocate a section of PMA
|
||||
*
|
||||
* If the EP number has already been allocated, and the new allocation
|
||||
* is larger than the old allocation, then this will fail with a TU_ASSERT.
|
||||
* (This is done to simplify the code. More complicated algorithms could be used)
|
||||
*
|
||||
* During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually.
|
||||
*/
|
||||
static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
xfer_ctl_t* epXferCtl = xfer_ctl_ptr(epnum,dir);
|
||||
|
||||
if(epXferCtl->pma_alloc_size != 0U)
|
||||
{
|
||||
//TU_LOG2("dcd_pma_alloc(%x,%x)=%x (cached)\r\n",ep_addr,length,epXferCtl->pma_ptr);
|
||||
// Previously allocated
|
||||
TU_ASSERT(length <= epXferCtl->pma_alloc_size, 0xFFFF); // Verify no larger than previous alloc
|
||||
return epXferCtl->pma_ptr;
|
||||
}
|
||||
|
||||
uint16_t addr = ep_buf_ptr;
|
||||
ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer
|
||||
|
||||
// Verify no overflow
|
||||
TU_ASSERT(ep_buf_ptr <= PMA_LENGTH, 0xFFFF);
|
||||
|
||||
epXferCtl->pma_ptr = addr;
|
||||
epXferCtl->pma_alloc_size = length;
|
||||
//TU_LOG2("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/***
|
||||
* Free a block of PMA space
|
||||
*/
|
||||
static void dcd_pma_free(uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
// Presently, this should never be called for EP0 IN/OUT
|
||||
TU_ASSERT(open_ep_count > 2, /**/);
|
||||
TU_ASSERT(xfer_ctl_ptr(epnum,dir)->max_packet_size != 0, /**/);
|
||||
open_ep_count--;
|
||||
|
||||
// If count is 2, only EP0 should be open, so allocations can be mostly reset.
|
||||
|
||||
if(open_ep_count == 2)
|
||||
{
|
||||
ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT + 2*CFG_TUD_ENDPOINT0_SIZE; // 8 bytes per endpoint (two TX and two RX words, each), and EP0
|
||||
|
||||
// Skip EP0
|
||||
for(uint32_t i=1; i<MAX_EP_COUNT; i++)
|
||||
{
|
||||
xfer_ctl_ptr(i,TUSB_DIR_OUT)->pma_alloc_size = 0U;
|
||||
xfer_ctl_ptr(i,TUSB_DIR_IN)->pma_alloc_size = 0U;
|
||||
xfer_ctl_ptr(i,TUSB_DIR_OUT)->pma_ptr = 0U;
|
||||
xfer_ctl_ptr(i,TUSB_DIR_IN)->pma_ptr = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers,
|
||||
// so I'm using the #define from HAL here, instead.
|
||||
|
||||
@@ -601,28 +678,30 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc
|
||||
uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
|
||||
uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
|
||||
const uint16_t epMaxPktSize = p_endpoint_desc->wMaxPacketSize.size;
|
||||
uint16_t pma_addr;
|
||||
uint32_t wType;
|
||||
|
||||
// Isochronous not supported (yet), and some other driver assumptions.
|
||||
|
||||
TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS);
|
||||
TU_ASSERT(epnum < MAX_EP_COUNT);
|
||||
|
||||
// Set type
|
||||
switch(p_endpoint_desc->bmAttributes.xfer) {
|
||||
case TUSB_XFER_CONTROL:
|
||||
pcd_set_eptype(USB, epnum, USB_EP_CONTROL);
|
||||
wType = USB_EP_CONTROL;
|
||||
break;
|
||||
#if (0)
|
||||
case TUSB_XFER_ISOCHRONOUS: // FIXME: Not yet supported
|
||||
pcd_set_eptype(USB, epnum, USB_EP_ISOCHRONOUS); break;
|
||||
wType = USB_EP_ISOCHRONOUS;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TUSB_XFER_BULK:
|
||||
pcd_set_eptype(USB, epnum, USB_EP_BULK);
|
||||
wType = USB_EP_CONTROL;
|
||||
break;
|
||||
|
||||
case TUSB_XFER_INTERRUPT:
|
||||
pcd_set_eptype(USB, epnum, USB_EP_INTERRUPT);
|
||||
wType = USB_EP_INTERRUPT;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -630,32 +709,59 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc
|
||||
return false;
|
||||
}
|
||||
|
||||
pcd_set_eptype(USB, epnum, wType);
|
||||
pcd_set_ep_address(USB, epnum, epnum);
|
||||
// Be normal, for now, instead of only accepting zero-byte packets (on control endpoint)
|
||||
// or being double-buffered (bulk endpoints)
|
||||
pcd_clear_ep_kind(USB,0);
|
||||
|
||||
pma_addr = dcd_pma_alloc(p_endpoint_desc->bEndpointAddress, p_endpoint_desc->wMaxPacketSize.size);
|
||||
|
||||
if(dir == TUSB_DIR_IN)
|
||||
{
|
||||
*pcd_ep_tx_address_ptr(USB, epnum) = ep_buf_ptr;
|
||||
*pcd_ep_tx_address_ptr(USB, epnum) = pma_addr;
|
||||
pcd_set_ep_tx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size);
|
||||
pcd_clear_tx_dtog(USB, epnum);
|
||||
pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pcd_ep_rx_address_ptr(USB, epnum) = ep_buf_ptr;
|
||||
*pcd_ep_rx_address_ptr(USB, epnum) = pma_addr;
|
||||
pcd_set_ep_rx_cnt(USB, epnum, p_endpoint_desc->wMaxPacketSize.size);
|
||||
pcd_clear_rx_dtog(USB, epnum);
|
||||
pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_NAK);
|
||||
}
|
||||
|
||||
xfer_ctl_ptr(epnum, dir)->max_packet_size = epMaxPktSize;
|
||||
ep_buf_ptr = (uint16_t)(ep_buf_ptr + p_endpoint_desc->wMaxPacketSize.size); // increment buffer pointer
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close an endpoint.
|
||||
*
|
||||
* This function may be called with interrupts enabled or disabled.
|
||||
*
|
||||
* This also clears transfers in progress, should there be any.
|
||||
*/
|
||||
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void)rhport;
|
||||
uint32_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint32_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
if(dir == TUSB_DIR_IN)
|
||||
{
|
||||
pcd_set_ep_tx_status(USB,epnum,USB_EP_TX_DIS);
|
||||
}
|
||||
else
|
||||
{
|
||||
pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_DIS);
|
||||
}
|
||||
|
||||
dcd_pma_free(ep_addr);
|
||||
}
|
||||
|
||||
// Currently, single-buffered, and only 64 bytes at a time (max)
|
||||
|
||||
static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix)
|
||||
|
||||
@@ -209,10 +209,6 @@ void dcd_init (uint8_t rhport)
|
||||
|
||||
// Enable USB transceiver.
|
||||
USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN;
|
||||
|
||||
// Soft Connect -> Enable pullup on D+/D-.
|
||||
// This step does not appear to be specified in the programmer's model.
|
||||
dev->DCTL &= ~USB_OTG_DCTL_SDIS;
|
||||
}
|
||||
|
||||
void dcd_int_enable (uint8_t rhport)
|
||||
@@ -250,6 +246,23 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
USB_OTG_DeviceTypeDef * dev = DEVICE_BASE;
|
||||
|
||||
dev->DCTL &= ~USB_OTG_DCTL_SDIS;
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
USB_OTG_DeviceTypeDef * dev = DEVICE_BASE;
|
||||
|
||||
dev->DCTL |= USB_OTG_DCTL_SDIS;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* DCD Endpoint port
|
||||
*------------------------------------------------------------------*/
|
||||
@@ -656,7 +669,7 @@ static void handle_epin_ints(USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointType
|
||||
}
|
||||
}
|
||||
|
||||
void dcd_irq_handler(uint8_t rhport) {
|
||||
void dcd_int_handler(uint8_t rhport) {
|
||||
|
||||
(void) rhport;
|
||||
|
||||
|
||||
@@ -91,6 +91,18 @@ void dcd_remote_wakeup (uint8_t rhport)
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
// Connect by enabling internal pull-up resistor on D+/D-
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
// Disconnect by disabling internal pull-up resistor on D+/D-
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@@ -134,9 +134,6 @@ void dcd_init (uint8_t rhport)
|
||||
// Enable reset and wait for it before continuing.
|
||||
USBIE |= RSTRIE;
|
||||
|
||||
// Enable pullup.
|
||||
USBCNF |= PUR_EN;
|
||||
|
||||
USBKEYPID = 0;
|
||||
}
|
||||
|
||||
@@ -207,6 +204,28 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
dcd_int_disable(rhport);
|
||||
|
||||
USBKEYPID = USBKEY;
|
||||
USBCNF |= PUR_EN; // Enable pullup.
|
||||
USBKEYPID = 0;
|
||||
|
||||
dcd_int_enable(rhport);
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
dcd_int_disable(rhport);
|
||||
|
||||
USBKEYPID = USBKEY;
|
||||
USBCNF &= ~PUR_EN; // Disable pullup.
|
||||
USBKEYPID = 0;
|
||||
|
||||
dcd_int_enable(rhport);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* DCD Endpoint port
|
||||
*------------------------------------------------------------------*/
|
||||
@@ -539,7 +558,7 @@ static void handle_setup_packet(void)
|
||||
dcd_event_setup_received(0, (uint8_t*) &_setup_packet[0], true);
|
||||
}
|
||||
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
|
||||
@@ -397,6 +397,19 @@ void dcd_remote_wakeup(uint8_t rhport)
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
usb_pullup_out_write(1);
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
usb_pullup_out_write(0);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// DCD Endpoint Port
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -613,7 +626,7 @@ static void handle_setup(void)
|
||||
|
||||
usb_setup_ev_pending_write(1);
|
||||
}
|
||||
void dcd_irq_handler(uint8_t rhport)
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
(void)rhport;
|
||||
uint8_t next_ev;
|
||||
|
||||
@@ -124,15 +124,6 @@
|
||||
#define OPT_MODE_HIGH_SPEED 0x10 ///< High speed
|
||||
/** @} */
|
||||
|
||||
/** \defgroup group_supported_netif Supported Network Interface
|
||||
* \ref CFG_TUD_NET must be defined to one of these
|
||||
* @{ */
|
||||
#define OPT_NET_NONE 0 ///< No network interface
|
||||
#define OPT_NET_ECM 1 ///< CDC-ECM
|
||||
#define OPT_NET_RNDIS 2 ///< RNDIS
|
||||
#define OPT_NET_EEM 3 ///< CDC-EEM
|
||||
/** @} */
|
||||
|
||||
#ifndef CFG_TUSB_RHPORT0_MODE
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user