CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2

Dependents:   USBEthernet_TEST

Fork of USB_Ethernet by Daniele Lacamera

USBCDC_ECM.cpp

Committer:
daniele
Date:
2013-08-02
Revision:
0:34c829fbc7a8
Child:
1:759afa79ebe8

File content as of revision 0:34c829fbc7a8:

/* Copyright (c) 2010-2011 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include "stdint.h"
#include "USBCDC_ECM.h"

static uint8_t cdc_line_coding[7]= {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08};

#define DEFAULT_CONFIGURATION (1)

#define CDC_SET_LINE_CODING        0x20
#define CDC_GET_LINE_CODING        0x21
#define CDC_SET_CONTROL_LINE_STATE 0x22

#define MAX_CDC_REPORT_SIZE MAX_PACKET_SIZE_EPBULK

USBCDC_ECM::USBCDC_ECM(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) {
    terminal_connected = false;
    USBDevice::connect();   
}

bool USBCDC_ECM::USBCallback_request(void) {
    /* Called in ISR context */

    bool success = false;
    CONTROL_TRANSFER * transfer = getTransferPtr();
   
    if (transfer->setup.bmRequestType.Type == STANDARD_TYPE) {
        printf("In USBCallback_request: GENERIC Request: %02x\n", transfer->setup.bRequest);
    } else if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
        printf("In USBCallback_request: CLASS specific Request: %02x\n", transfer->setup.bRequest);
        switch (transfer->setup.bRequest) {
            default:
                    break;
        }
    }

    return success;
}

bool USBCDC_ECM::USBCallback_setInterface(uint16_t interface, uint8_t alternate) 
{ 
    printf("Host selected interface %d, alternate %d\n", interface, alternate);
    return true; 
}


// Called in ISR context
// Set configuration. Return false if the
// configuration is not supported.
bool USBCDC_ECM::USBCallback_setConfiguration(uint8_t configuration) {
    printf("In USBCallback_SetConfiguration: %02x\n", configuration);
    if (configuration != DEFAULT_CONFIGURATION) {
        printf("Set config: failed\n");
        return false;
    }

    // Configure endpoints > 0
    addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
    addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
    addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);

    // We activate the endpoint to be able to recceive data
    readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
    printf("Set config: OK!\n");
    return true;
}

bool USBCDC_ECM::send(uint8_t * buffer, uint32_t size) {
    return USBDevice::write(EPBULK_IN, buffer, size, MAX_CDC_REPORT_SIZE);
}

bool USBCDC_ECM::readEP(uint8_t * buffer, uint32_t * size) {
    if (!USBDevice::readEP(EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE))
        return false;
    if (!readStart(EPBULK_OUT, MAX_CDC_REPORT_SIZE))
        return false;
    return true;
}

bool USBCDC_ECM::readEP_NB(uint8_t * buffer, uint32_t * size) {
    if (!USBDevice::readEP_NB(EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE))
        return false;
    if (!readStart(EPBULK_OUT, MAX_CDC_REPORT_SIZE))
        return false;
    return true;
}


uint8_t * USBCDC_ECM::deviceDesc() {
    static uint8_t deviceDescriptor[] = {
        18,                   // bLength
        1,                    // bDescriptorType
        0x10, 0x01,           // bcdUSB
        2,                    // bDeviceClass
        0,                    // bDeviceSubClass
        0,                    // bDeviceProtocol
        MAX_PACKET_SIZE_EP0,  // bMaxPacketSize0
        LSB(VENDOR_ID), MSB(VENDOR_ID),  // idVendor
        LSB(PRODUCT_ID), MSB(PRODUCT_ID),// idProduct
        0x00, 0x01,           // bcdDevice
        1,                    // iManufacturer
        2,                    // iProduct
        3,                    // iSerialNumber
        4,                    // iMacAddress
        1                     // bNumConfigurations
    };
    return deviceDescriptor;
}

uint8_t * USBCDC_ECM::stringIinterfaceDesc() {
    static uint8_t stringIinterfaceDescriptor[] = {
        0x08,
        STRING_DESCRIPTOR,
        'C',0,'D',0,'C',0,
    };
    return stringIinterfaceDescriptor;
}

uint8_t * USBCDC_ECM::stringIproductDesc() {
    static uint8_t stringIproductDescriptor[] = {
        36,
        STRING_DESCRIPTOR,
        'M',0,'B',0,'E',0,'D',0,' ',0,'C',0,'D',0,'C',0,'-',0,'E',0,'T',0,'H',0,'E',0,'R',0,'N',0,'E',0,'T',0
    };
    return stringIproductDescriptor;
}

uint8_t * USBCDC_ECM::stringIserialDesc() {
    static uint8_t stringIserialDescriptor[] = {
        26,
        STRING_DESCRIPTOR,
        '0',0,'0',0,
        '5', 0,'a',0,
        'f',0,'3',0,
        '4',0,'1',0,
        'b',0,'4',0,
        'c',0,'7',0
    };
    return stringIserialDescriptor;
}

uint8_t * USBCDC_ECM::stringIConfigurationDesc() {
    static uint8_t stringImacAddr[] = {
        26,
        STRING_DESCRIPTOR,
        '0',0,'0',0,
        '5', 0,'a',0,
        'f',0,'3',0,
        '4',0,'1',0,
        'b',0,'4',0,
        'c',0,'7',0
    };
    return stringImacAddr;
}

#define CONFIG1_DESC_SIZE (9+9+5+5+13+7+9+7+7)

uint8_t * USBCDC_ECM::configurationDesc() {
    static uint8_t configDescriptor[] = {
        // configuration descriptor
        9,                      // bLength
        2,                      // bDescriptorType
        LSB(CONFIG1_DESC_SIZE), // wTotalLength
        MSB(CONFIG1_DESC_SIZE),
        2,                      // bNumInterfaces
        1,                      // bConfigurationValue
        0,                      // iConfiguration
        0xc0,                   // bmAttributes
        50,                     // bMaxPower

        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                      // bLength
        4,                      // bDescriptorType
        0,                      // bInterfaceNumber
        0,                      // bAlternateSetting
        1,                      // bNumEndpoints
        0x02,                   // bInterfaceClass
        0x06,                   // bInterfaceSubClass
        0x00,                   // bInterfaceProtocol
        0,                      // iInterface
        
        // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
        5,                      // bFunctionLength
        0x24,                   // bDescriptorType
        0x00,                   // bDescriptorSubtype
        0x20, 0x01,             // bcdCDC
        
        // CDC Union
        5,                      // bFunctionLength
        0x24,                   // bDescriptorType
        0x06,                   // bDescriptorSubType
        0,                      // bControlInterface
        1,                      // bSubordinateInterface0
        
        
        
        // CDC/ECM Functional Descriptor
        13,                      // bFunctionLenght
        0x24,                    // bDescriptorType
        0x0F,                    // bDescriptorSubtype        
        4,                       // iMacAddress
        0, 0, 0, 0,              // bmEthernetStatistics
        
        0x05, 0xEA,              // wMaxSegmentSize

        
        0, 0,                   // wNumberMCFilters
        
        0,                      // bNumberPowerFilters
        
        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
        ENDPOINT_DESCRIPTOR,            // bDescriptorType
        PHY_TO_DESC(EPINT_IN),          // bEndpointAddress
        0x03  ,                         // bmAttributes (0x03=intr)
        LSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (LSB)
        MSB(MAX_PACKET_SIZE_EPINT),     // wMaxPacketSize (MSB)
        16,

        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                          // bLength
        4,                          // bDescriptorType
        1,                          // bInterfaceNumber
        0,                          // bAlternateSetting
        2,                          // bNumEndpoints
        0x0A,                       // bInterfaceClass
        0x00,                       // bInterfaceSubClass
        0x00,                       // bInterfaceProtocol
        0,                          // iInterface

        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
        ENDPOINT_DESCRIPTOR_LENGTH, // bLength
        ENDPOINT_DESCRIPTOR,        // bDescriptorType
        PHY_TO_DESC(EPBULK_IN),     // bEndpointAddress
        E_BULK,                     // bmAttributes (0x02=bulk)
        LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
        MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
        0,                          // bInterval

        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
        ENDPOINT_DESCRIPTOR_LENGTH, // bLength
        ENDPOINT_DESCRIPTOR,        // bDescriptorType
        PHY_TO_DESC(EPBULK_OUT),    // bEndpointAddress
        E_BULK,                     // bmAttributes (0x02=bulk)
        LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
        MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
        0                           // bInterval
    };
    return configDescriptor;
}