mirror of https://github.com/ARMmbed/mbed-os.git
USBCDC_ECM: Add receive functionality
Handle SET_ETHERNET_PACKET_FILTER requestpull/9443/head
parent
fc00718917
commit
87f2f7f93f
|
@ -22,11 +22,14 @@
|
||||||
#include "mbed_interface.h"
|
#include "mbed_interface.h"
|
||||||
#include "mbed_assert.h"
|
#include "mbed_assert.h"
|
||||||
|
|
||||||
#define MAX_SEGMENT_SIZE (1514)
|
#ifndef MAX_SEGMENT_SIZE
|
||||||
#define FLAG_WRITE_DONE (1 << 0)
|
#define MAX_SEGMENT_SIZE (1514)
|
||||||
#define FLAG_DISCONNECT (1 << 1)
|
#endif
|
||||||
#define FLAG_CONNECT (1 << 2)
|
|
||||||
#define FLAG_INT_DONE (1 << 3)
|
#define FLAG_WRITE_DONE (1 << 0)
|
||||||
|
#define FLAG_DISCONNECT (1 << 1)
|
||||||
|
#define FLAG_CONNECT (1 << 2)
|
||||||
|
#define FLAG_INT_DONE (1 << 3)
|
||||||
|
|
||||||
#define SET_ETHERNET_MULTICAST_FILTERS 0x40
|
#define SET_ETHERNET_MULTICAST_FILTERS 0x40
|
||||||
#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x41
|
#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x41
|
||||||
|
@ -34,19 +37,13 @@
|
||||||
#define SET_ETHERNET_PACKET_FILTER 0x43
|
#define SET_ETHERNET_PACKET_FILTER 0x43
|
||||||
#define GET_ETHERNET_STATISTIC 0x44
|
#define GET_ETHERNET_STATISTIC 0x44
|
||||||
|
|
||||||
#define PACKET_TYPE_PROMISCUOUS (1<<0)
|
|
||||||
#define PACKET_TYPE_ALL_MULTICAST (1<<1)
|
|
||||||
#define PACKET_TYPE_DIRECTED (1<<2)
|
|
||||||
#define PACKET_TYPE_BROADCAST (1<<3)
|
|
||||||
#define PACKET_TYPE_MULTICAST (1<<4)
|
|
||||||
|
|
||||||
#define CS_INTERFACE 0x24
|
#define CS_INTERFACE 0x24
|
||||||
#define NETWORK_CONNECTION 0x00
|
#define NETWORK_CONNECTION 0x00
|
||||||
#define CONNECTION_SPEED_CHANGE 0x2A
|
#define CONNECTION_SPEED_CHANGE 0x2A
|
||||||
#define LINK_SPEED (10000000)
|
#define LINK_SPEED (10000000)
|
||||||
|
|
||||||
USBCDC_ECM::USBCDC_ECM(bool connect_blocking, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
|
USBCDC_ECM::USBCDC_ECM(bool connect_blocking, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
|
||||||
: USBDevice(get_usb_phy(), vendor_id, product_id, product_release), _queue(4 * EVENTS_EVENT_SIZE)
|
: USBDevice(get_usb_phy(), vendor_id, product_id, product_release), _packet_filter(0), _queue(4 * EVENTS_EVENT_SIZE)
|
||||||
{
|
{
|
||||||
_init();
|
_init();
|
||||||
|
|
||||||
|
@ -60,7 +57,7 @@ USBCDC_ECM::USBCDC_ECM(bool connect_blocking, uint16_t vendor_id, uint16_t produ
|
||||||
}
|
}
|
||||||
|
|
||||||
USBCDC_ECM::USBCDC_ECM(USBPhy *phy, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
|
USBCDC_ECM::USBCDC_ECM(USBPhy *phy, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
|
||||||
: USBDevice(phy, vendor_id, product_id, product_release), _queue(4 * EVENTS_EVENT_SIZE)
|
: USBDevice(phy, vendor_id, product_id, product_release), _packet_filter(0), _queue(4 * EVENTS_EVENT_SIZE)
|
||||||
{
|
{
|
||||||
|
|
||||||
_init();
|
_init();
|
||||||
|
@ -235,6 +232,41 @@ bool USBCDC_ECM::send(uint8_t *buffer, uint32_t size)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void USBCDC_ECM::receive_nb(uint8_t *buffer, uint32_t size, uint32_t *actual)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
|
||||||
|
uint32_t available = _rx_queue.size();
|
||||||
|
uint32_t copy_size = available > size ? size : available;
|
||||||
|
_rx_queue.read(buffer, copy_size);
|
||||||
|
*actual = copy_size;
|
||||||
|
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC_ECM::attach_rx(mbed::Callback<void()> cb)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
|
||||||
|
_callback_rx = cb;
|
||||||
|
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBCDC_ECM::attach_filter(mbed::Callback<void()> cb)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
|
||||||
|
_callback_filter = cb;
|
||||||
|
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t USBCDC_ECM::read_packet_filter()
|
||||||
|
{
|
||||||
|
return _packet_filter;
|
||||||
|
}
|
||||||
|
|
||||||
void USBCDC_ECM::callback_request(const setup_packet_t *setup)
|
void USBCDC_ECM::callback_request(const setup_packet_t *setup)
|
||||||
{
|
{
|
||||||
assert_locked();
|
assert_locked();
|
||||||
|
@ -247,30 +279,26 @@ void USBCDC_ECM::callback_request(const setup_packet_t *setup)
|
||||||
//printf("In USBCallback_request: CLASS specific Request: %02x\n", setup->bRequest);
|
//printf("In USBCallback_request: CLASS specific Request: %02x\n", setup->bRequest);
|
||||||
switch (setup->bRequest) {
|
switch (setup->bRequest) {
|
||||||
case SET_ETHERNET_MULTICAST_FILTERS:
|
case SET_ETHERNET_MULTICAST_FILTERS:
|
||||||
|
/* TODO: Support is optional, not implemented here */
|
||||||
break;
|
break;
|
||||||
case SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER:
|
case SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER:
|
||||||
|
/* TODO: Support is optional, not implemented here */
|
||||||
break;
|
break;
|
||||||
case GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER:
|
case GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER:
|
||||||
|
/* TODO: Support is optional, not implemented here */
|
||||||
break;
|
break;
|
||||||
case SET_ETHERNET_PACKET_FILTER:
|
case SET_ETHERNET_PACKET_FILTER:
|
||||||
/*if (setup->wValue & PACKET_TYPE_PROMISCUOUS) {
|
if (_packet_filter != setup->wValue) {
|
||||||
printf("PROMISCUOUS\n");
|
_packet_filter = setup->wValue;
|
||||||
|
// Signal that packet filter configuration is changed
|
||||||
|
if (_callback_filter) {
|
||||||
|
_callback_filter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (setup->wValue & PACKET_TYPE_ALL_MULTICAST) {
|
|
||||||
printf("ALL_MULTICAST\n");
|
|
||||||
}
|
|
||||||
if (setup->wValue & PACKET_TYPE_DIRECTED) {
|
|
||||||
printf("DIRECTED\n");
|
|
||||||
}
|
|
||||||
if (setup->wValue & PACKET_TYPE_BROADCAST) {
|
|
||||||
printf("BROADCAST\n");
|
|
||||||
}
|
|
||||||
if (setup->wValue & PACKET_TYPE_MULTICAST) {
|
|
||||||
printf("MULTICAST\n");
|
|
||||||
}*/
|
|
||||||
result = Success;
|
result = Success;
|
||||||
break;
|
break;
|
||||||
case GET_ETHERNET_STATISTIC:
|
case GET_ETHERNET_STATISTIC:
|
||||||
|
/* TODO: Support is optional, not implemented here */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = Failure;
|
result = Failure;
|
||||||
|
@ -287,6 +315,9 @@ void USBCDC_ECM::callback_set_interface(uint16_t interface, uint8_t alternate)
|
||||||
/* Called in ISR context */
|
/* Called in ISR context */
|
||||||
|
|
||||||
if (alternate) {
|
if (alternate) {
|
||||||
|
_packet_filter = 0;
|
||||||
|
_rx_queue.resize(MAX_SEGMENT_SIZE);
|
||||||
|
|
||||||
endpoint_add(_int_in, MAX_PACKET_SIZE_INT, USB_EP_TYPE_INT, &USBCDC_ECM::_int_callback);
|
endpoint_add(_int_in, MAX_PACKET_SIZE_INT, USB_EP_TYPE_INT, &USBCDC_ECM::_int_callback);
|
||||||
endpoint_add(_bulk_in, MAX_PACKET_SIZE_BULK, USB_EP_TYPE_BULK, &USBCDC_ECM::_bulk_in_callback);
|
endpoint_add(_bulk_in, MAX_PACKET_SIZE_BULK, USB_EP_TYPE_BULK, &USBCDC_ECM::_bulk_in_callback);
|
||||||
endpoint_add(_bulk_out, MAX_PACKET_SIZE_BULK, USB_EP_TYPE_BULK, &USBCDC_ECM::_bulk_out_callback);
|
endpoint_add(_bulk_out, MAX_PACKET_SIZE_BULK, USB_EP_TYPE_BULK, &USBCDC_ECM::_bulk_out_callback);
|
||||||
|
@ -511,7 +542,17 @@ void USBCDC_ECM::_bulk_out_callback()
|
||||||
{
|
{
|
||||||
assert_locked();
|
assert_locked();
|
||||||
|
|
||||||
_bulk_buf_size = read_finish(_bulk_out);
|
uint32_t read_size = read_finish(_bulk_out);
|
||||||
|
|
||||||
|
if (read_size <= _rx_queue.free()) {
|
||||||
|
// Copy data over
|
||||||
|
_rx_queue.write(_bulk_buf, read_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal that there is ethernet packet available
|
||||||
|
if (_callback_rx && (read_size < USBDevice::endpoint_max_packet_size(_bulk_out))) {
|
||||||
|
_callback_rx();
|
||||||
|
}
|
||||||
|
|
||||||
read_start(_bulk_out, _bulk_buf, MAX_PACKET_SIZE_BULK);
|
read_start(_bulk_out, _bulk_buf, MAX_PACKET_SIZE_BULK);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,17 +20,24 @@
|
||||||
|
|
||||||
#include "USBDescriptor.h"
|
#include "USBDescriptor.h"
|
||||||
#include "USBDevice.h"
|
#include "USBDevice.h"
|
||||||
|
#include "ByteBuffer.h"
|
||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "EventFlags.h"
|
#include "EventFlags.h"
|
||||||
#include "EventQueue.h"
|
#include "EventQueue.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
|
#include "Callback.h"
|
||||||
|
|
||||||
#define MAX_PACKET_SIZE_INT (64)
|
#define MAX_PACKET_SIZE_INT (64)
|
||||||
#define MAX_PACKET_SIZE_BULK (64)
|
#define MAX_PACKET_SIZE_BULK (64)
|
||||||
#define MAX_PACKET_SIZE_EP0 (64)
|
#define MAX_PACKET_SIZE_EP0 (64)
|
||||||
#define DEFAULT_CONFIGURATION (1)
|
#define DEFAULT_CONFIGURATION (1)
|
||||||
|
|
||||||
|
#define PACKET_TYPE_PROMISCUOUS (1<<0)
|
||||||
|
#define PACKET_TYPE_ALL_MULTICAST (1<<1)
|
||||||
|
#define PACKET_TYPE_DIRECTED (1<<2)
|
||||||
|
#define PACKET_TYPE_BROADCAST (1<<3)
|
||||||
|
#define PACKET_TYPE_MULTICAST (1<<4)
|
||||||
|
|
||||||
class USBCDC_ECM: public USBDevice {
|
class USBCDC_ECM: public USBDevice {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -98,6 +105,45 @@ public:
|
||||||
*/
|
*/
|
||||||
bool send(uint8_t *buffer, uint32_t size);
|
bool send(uint8_t *buffer, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read from the receive buffer
|
||||||
|
*
|
||||||
|
* @param buffer buffer to fill with data
|
||||||
|
* @param size maximum number of bytes read
|
||||||
|
* @param actual a pointer to where to store the number of bytes actually received
|
||||||
|
*/
|
||||||
|
void receive_nb(uint8_t *buffer, uint32_t size, uint32_t *actual);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return ethernet packet filter bitmap
|
||||||
|
*
|
||||||
|
* The Packet Filter is the inclusive OR of the bitmap
|
||||||
|
* D0: PACKET_TYPE_PROMISCUOUS
|
||||||
|
* D1: PACKET_TYPE_ALL_MULTICAST
|
||||||
|
* D2: PACKET_TYPE_DIRECTED
|
||||||
|
* D3: PACKET_TYPE_BROADCAST
|
||||||
|
* D4: PACKET_TYPE_MULTICAST
|
||||||
|
* D5-D15: Reserved (zero)
|
||||||
|
*
|
||||||
|
* @return ethernet packet filter bitmap
|
||||||
|
*/
|
||||||
|
uint16_t read_packet_filter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a callback for when an ethernet packet is received
|
||||||
|
*
|
||||||
|
* @param cb code to call when a packet is received
|
||||||
|
*/
|
||||||
|
void attach_rx(mbed::Callback<void()> cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a callback for when a request to configure device ethernet
|
||||||
|
* packet filter is received
|
||||||
|
*
|
||||||
|
* @param cb code to call when a packet filter request is received
|
||||||
|
*/
|
||||||
|
void attach_filter(mbed::Callback<void()> cb);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -200,13 +246,16 @@ private:
|
||||||
uint8_t _string_imac_addr[26];
|
uint8_t _string_imac_addr[26];
|
||||||
|
|
||||||
uint8_t _bulk_buf[MAX_PACKET_SIZE_BULK];
|
uint8_t _bulk_buf[MAX_PACKET_SIZE_BULK];
|
||||||
uint32_t _bulk_buf_size;
|
uint16_t _packet_filter;
|
||||||
|
ByteBuffer _rx_queue;
|
||||||
|
|
||||||
rtos::EventFlags _flags;
|
rtos::EventFlags _flags;
|
||||||
rtos::Mutex _write_mutex;
|
rtos::Mutex _write_mutex;
|
||||||
|
|
||||||
events::EventQueue _queue;
|
events::EventQueue _queue;
|
||||||
rtos::Thread _thread;
|
rtos::Thread _thread;
|
||||||
|
mbed::Callback<void()> _callback_rx;
|
||||||
|
mbed::Callback<void()> _callback_filter;
|
||||||
|
|
||||||
void _init();
|
void _init();
|
||||||
void _int_callback();
|
void _int_callback();
|
||||||
|
|
Loading…
Reference in New Issue