From 110bc0242e3f4519b07503d95b21658592b28261 Mon Sep 17 00:00:00 2001 From: dak664 Date: Fri, 17 Sep 2010 21:59:09 +0000 Subject: [PATCH] Merge CDC-ECM, RNG, DFU bootloader, watchdog, settings manager, energy scan routines of Robert Quattlebaum --- cpu/avr/Makefile.avr | 4 +- cpu/avr/bootloader.c | 59 ++ cpu/avr/bootloader.h | 24 + cpu/avr/dev/usb/conf_usb.h | 8 + cpu/avr/dev/usb/rndis/cdc_ecm.c | 327 +++++++ cpu/avr/dev/usb/rndis/cdc_ecm.h | 18 + cpu/avr/dev/usb/rndis/cdc_eem.c | 296 +++++++ cpu/avr/dev/usb/rndis/cdc_eem.h | 12 + cpu/avr/dev/usb/rndis/rndis.c | 395 +++++++-- cpu/avr/dev/usb/rndis/rndis_protocol.h | 13 +- cpu/avr/dev/usb/rndis/rndis_task.c | 801 +++++------------ cpu/avr/dev/usb/rndis/rndis_task.h | 58 +- cpu/avr/dev/usb/serial/cdc_task.c | 383 --------- cpu/avr/dev/usb/serial/cdc_task.h | 74 -- cpu/avr/dev/usb/serial/uart_usb_lib.c | 157 +++- cpu/avr/dev/usb/serial/uart_usb_lib.h | 4 + cpu/avr/dev/usb/usb_descriptors.c | 802 +++++++++--------- cpu/avr/dev/usb/usb_descriptors.h | 238 +++--- cpu/avr/dev/usb/usb_drv.c | 97 +++ cpu/avr/dev/usb/usb_drv.h | 9 +- cpu/avr/dev/usb/usb_specific_request.c | 357 ++++---- cpu/avr/dev/usb/usb_specific_request.h | 7 +- cpu/avr/dev/usb/usb_standard_request.c | 448 +++++++--- cpu/avr/dev/usb/usb_task.c | 75 +- cpu/avr/radio/rf230bb/rf230bb.c | 268 +++--- cpu/avr/radio/rf230bb/rf230bb.h | 108 +-- cpu/avr/settings.c | 275 ++++++ cpu/avr/settings.h | 118 +++ cpu/avr/watchdog.c | 19 +- platform/avr-raven/contiki-raven-main.c | 47 +- platform/avr-ravenusb/Makefile.avr-ravenusb | 13 +- platform/avr-ravenusb/cdc_task.c | 578 +++++++++++++ platform/avr-ravenusb/cdc_task.h | 74 ++ platform/avr-ravenusb/contiki-conf.h | 132 ++- .../contiki-raven-default-init-lowlevel.c | 3 + .../contiki-raven-default-init-net.c | 64 +- platform/avr-ravenusb/contiki-raven-main.c | 187 +++- platform/avr-ravenusb/contiki-raven.h | 4 +- platform/avr-ravenusb/fakeuip.c | 129 --- platform/avr-ravenusb/rng.c | 218 +++++ platform/avr-ravenusb/rng.h | 13 + platform/avr-ravenusb/sicslow_ethernet.c | 492 +++++------ 42 files changed, 4739 insertions(+), 2669 deletions(-) create mode 100644 cpu/avr/bootloader.c create mode 100644 cpu/avr/bootloader.h create mode 100644 cpu/avr/dev/usb/rndis/cdc_ecm.c create mode 100644 cpu/avr/dev/usb/rndis/cdc_ecm.h create mode 100644 cpu/avr/dev/usb/rndis/cdc_eem.c create mode 100644 cpu/avr/dev/usb/rndis/cdc_eem.h create mode 100644 cpu/avr/settings.c create mode 100644 cpu/avr/settings.h create mode 100644 platform/avr-ravenusb/cdc_task.c create mode 100644 platform/avr-ravenusb/cdc_task.h delete mode 100644 platform/avr-ravenusb/fakeuip.c create mode 100644 platform/avr-ravenusb/rng.c create mode 100644 platform/avr-ravenusb/rng.h diff --git a/cpu/avr/Makefile.avr b/cpu/avr/Makefile.avr index 57182c9cb..db201a8f0 100644 --- a/cpu/avr/Makefile.avr +++ b/cpu/avr/Makefile.avr @@ -1,4 +1,4 @@ -# $Id: Makefile.avr,v 1.24 2010/06/22 17:11:38 dak664 Exp $ +# $Id: Makefile.avr,v 1.25 2010/09/17 21:59:09 dak664 Exp $ ### Check if we are running under Windows @@ -23,7 +23,7 @@ CONTIKI_CPU=$(CONTIKI)/cpu/avr ### These directories will be searched for the specified source files ### TARGETLIBS are platform-specific routines in the contiki library path CONTIKI_CPU_DIRS = . dev -AVR = clock.c mtarch.c eeprom.c flash.c rs232.c leds-arch.c watchdog.c rtimer-arch.c +AVR = clock.c mtarch.c eeprom.c flash.c rs232.c leds-arch.c watchdog.c rtimer-arch.c bootloader.c settings.c ELFLOADER = elfloader.c elfloader-avr.c symtab-avr.c TARGETLIBS = random.c leds.c diff --git a/cpu/avr/bootloader.c b/cpu/avr/bootloader.c new file mode 100644 index 000000000..b527cfff7 --- /dev/null +++ b/cpu/avr/bootloader.c @@ -0,0 +1,59 @@ +#include "bootloader.h" +#include "dev/watchdog.h" +#include +#include +#include "dev/usb/usb_drv.h" + +volatile uint32_t Boot_Key ATTR_NO_INIT; + +bool +bootloader_is_present(void) { + return pgm_read_word_far(BOOTLOADER_START_ADDRESS)!=0xFFFF; +} + +void +Jump_To_Bootloader(void) +{ + uint8_t i; + +#ifdef UDCON + // If USB is used, detach from the bus + Usb_detach(); +#endif + + // Disable all interrupts + cli(); + + // Set the bootloader key to the magic value and force a reset + Boot_Key = MAGIC_BOOT_KEY; + + // Wait two seconds for the USB detachment to register on the host + for (i = 0; i < 128; i++) + _delay_ms(16); + + // Set the bootloader key to the magic value and force a reset + Boot_Key = MAGIC_BOOT_KEY; + + watchdog_reboot(); +} + +extern void Bootloader_Jump_Check(void) ATTR_INIT_SECTION(3); + +void +Bootloader_Jump_Check(void) +{ + // If the reset source was the bootloader and the key is correct, clear it and jump to the bootloader + if(MCUSR & (1< +#include +#include + +#define ATTR_INIT_SECTION(SectionIndex) __attribute__ ((naked, section (".init" #SectionIndex ))) +#define ATTR_NO_INIT __attribute__ ((section (".noinit"))) + +#ifndef BOOTLOADER_SEC_SIZE_BYTES +#define BOOTLOADER_SEC_SIZE_BYTES (0x1000) +#endif + +#ifndef BOOTLOADER_START_ADDRESS +#define BOOTLOADER_START_ADDRESS (FLASHEND-BOOTLOADER_SEC_SIZE_BYTES+1) +#endif + +#define MAGIC_BOOT_KEY 0xDC42ACCA + +extern void Jump_To_Bootloader(void); +extern bool bootloader_is_present(void); + +#endif \ No newline at end of file diff --git a/cpu/avr/dev/usb/conf_usb.h b/cpu/avr/dev/usb/conf_usb.h index cdc15f53e..d98930a4d 100644 --- a/cpu/avr/dev/usb/conf_usb.h +++ b/cpu/avr/dev/usb/conf_usb.h @@ -94,6 +94,14 @@ /** USB RNDIS / Virtual com port setup **/ +#ifndef CDC_ECM_USES_INTERRUPT_ENDPOINT +#define CDC_ECM_USES_INTERRUPT_ENDPOINT 0 +#endif + +#ifndef USB_ETH_EMULATE_WIFI +#define USB_ETH_EMULATE_WIFI 0 +#endif + #define NB_ENDPOINTS 7 //! number of endpoints in the application including control endpoint #define VCP_RX_EP 0x06 #define VCP_TX_EP 0x05 diff --git a/cpu/avr/dev/usb/rndis/cdc_ecm.c b/cpu/avr/dev/usb/rndis/cdc_ecm.c new file mode 100644 index 000000000..4fd1d62ba --- /dev/null +++ b/cpu/avr/dev/usb/rndis/cdc_ecm.c @@ -0,0 +1,327 @@ +#include +#include "cdc_ecm.h" +#include "contiki.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" +#include "rndis/rndis_task.h" +#include "rndis/rndis_protocol.h" +#include "uip.h" +#include "sicslow_ethernet.h" +#include + +#include +#include + +#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) +#define PRINTF printf +#define PRINTF_P printf_P + +extern uint8_t usb_eth_data_buffer[64]; +static U16 usb_ecm_packet_filter = 0; + +#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 Usb_write_word(x) Usb_write_byte((x)&0xFF),Usb_write_byte((x>>8)&0xFF) +#define Usb_write_long(x) Usb_write_word((x)&0xFFFF),Usb_write_word((x>>16)&0xFFFF) + +#define Usb_read_word() ((U16)Usb_read_byte()+((U16)Usb_read_byte()<<8)) + +void +cdc_ecm_set_ethernet_packet_filter(void) { + usb_ecm_packet_filter = Usb_read_word(); + + Usb_ack_receive_setup(); + Usb_send_control_in(); + usb_endpoint_wait_for_read_control_enabled(); + + PRINTF_P(PSTR("cdc_ecm: Received SET_ETHERNET_PACKET_FILTER: (0x%04X) "),usb_ecm_packet_filter); + if(usb_ecm_packet_filter & PACKET_TYPE_PROMISCUOUS) { + PRINTF_P(PSTR("PROMISCUOUS ")); + USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true); + } else { + USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false); + } + + if(usb_ecm_packet_filter & PACKET_TYPE_ALL_MULTICAST) + PRINTF_P(PSTR("ALL_MULTICAST ")); + if(usb_ecm_packet_filter & PACKET_TYPE_DIRECTED) + PRINTF_P(PSTR("DIRECTED ")); + if(usb_ecm_packet_filter & PACKET_TYPE_BROADCAST) + PRINTF_P(PSTR("BROADCAST ")); + if(usb_ecm_packet_filter & PACKET_TYPE_MULTICAST) + PRINTF_P(PSTR("MULTICAST ")); + + PRINTF_P(PSTR("\n")); +} + + +#define CDC_NOTIFY_NETWORK_CONNECTION (0x00) +#define CDC_NOTIFY_CONNECTION_SPEED_CHANGE (0x2A) + +void +cdc_ecm_notify_network_connection(uint8_t value) { +#if CDC_ECM_USES_INTERRUPT_ENDPOINT + Usb_select_endpoint(INT_EP); + + if(!Is_usb_endpoint_enabled()) { + //PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: endpoint not enabled\n")); + return; + } + + if(usb_endpoint_wait_for_IN_ready()!=0) { + //PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: Timeout waiting for interrupt endpoint to be available\n")); + return; + } + + Usb_send_control_in(); + + Usb_write_byte(0x51); // 10100001b + Usb_write_byte(CDC_NOTIFY_NETWORK_CONNECTION); + Usb_write_byte(value); + Usb_write_byte(0x00); + Usb_write_word(ECM_INTERFACE0_NB); + Usb_write_word(0x0000); + + Usb_send_in(); + PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_NETWORK_CONNECTION %d\n"),value); +#endif +} + +#define CDC_ECM_DATA_ENDPOINT_SIZE 64 + +void cdc_ecm_configure_endpoints() { +#if CDC_ECM_USES_INTERRUPT_ENDPOINT + usb_configure_endpoint(INT_EP, \ + TYPE_INTERRUPT, \ + DIRECTION_IN, \ + SIZE_8, \ + TWO_BANKS, \ + NYET_ENABLED); +#endif + + usb_configure_endpoint(TX_EP, \ + TYPE_BULK, \ + DIRECTION_IN, \ + SIZE_64, \ + TWO_BANKS, \ + NYET_ENABLED); + + usb_configure_endpoint(RX_EP, \ + TYPE_BULK, \ + DIRECTION_OUT, \ + SIZE_64, \ + TWO_BANKS, \ + NYET_ENABLED); +#if CDC_ECM_USES_INTERRUPT_ENDPOINT + Usb_reset_endpoint(INT_EP); +#endif + Usb_reset_endpoint(TX_EP); + Usb_reset_endpoint(RX_EP); + usb_eth_is_active = 1; +} + + +void +cdc_ecm_notify_connection_speed_change(uint32_t upstream,uint32_t downstream) { +#if CDC_ECM_USES_INTERRUPT_ENDPOINT + Usb_select_endpoint(INT_EP); + + if(!Is_usb_endpoint_enabled()) + return; + + if(usb_endpoint_wait_for_IN_ready()!=0) + return; + + Usb_send_control_in(); + + Usb_write_byte(0x51); // 10100001b + Usb_write_byte(CDC_NOTIFY_CONNECTION_SPEED_CHANGE); + Usb_write_word(0x0000); + Usb_write_word(ECM_INTERFACE0_NB); + Usb_write_word(0x0008); + + Usb_send_in(); + + if(usb_endpoint_wait_for_write_enabled()!=0) + return; + + Usb_write_long(upstream); + Usb_write_long(downstream); + Usb_send_in(); + + PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_CONNECTION_SPEED_CHANGE UP:%d DOWN:%d\n"),upstream,downstream); +#endif +} + +void cdc_ecm_set_active(uint8_t value) { + if(value!=usb_eth_is_active) { + Led3_on(); + + usb_eth_is_active = value; + cdc_ecm_notify_network_connection(value); + if(value) { + cdc_ecm_notify_connection_speed_change(250000,250000); + } else { + cdc_ecm_notify_connection_speed_change(0,0); + } + } +} + +uint8_t +cdc_ecm_process(void) { + static uint8_t doInit = 1; + + Usb_select_endpoint(RX_EP); + + if(!Is_usb_endpoint_enabled()) { + return 0; + } + + if (doInit) { +#ifdef USB_ETH_HOOK_INIT + USB_ETH_HOOK_INIT(); +#endif + cdc_ecm_notify_network_connection(1); + cdc_ecm_notify_connection_speed_change(250000,250000); + doInit = 0; + if(usb_ecm_packet_filter & PACKET_TYPE_PROMISCUOUS) { +#if RF230BB + rf230_set_promiscuous_mode(true); +#else + radio_set_trx_state(RX_ON); +#endif + } + + // Select again, just to make sure. + Usb_select_endpoint(RX_EP); + } + + if(!usb_eth_is_active) { + // If we aren't active, just eat the packets. + if(Is_usb_read_enabled()) { + Usb_ack_receive_out(); + } + return 0; + } + + //Connected! + Led0_on(); + + if(Is_usb_read_enabled()) { + uint16_t bytecounter; + uint16_t bytes_received = 0; + U8 * buffer = uip_buf; + + if(!usb_eth_ready_for_next_packet()) { + // Since we aren't ready for a packet yet, + // just return. + goto bail; + } + +#ifdef USB_ETH_HOOK_RX_START + USB_ETH_HOOK_RX_START(); +#endif + + while((bytecounter=Usb_byte_counter_8())==CDC_ECM_DATA_ENDPOINT_SIZE) { + while((bytes_received +#include "conf_usb.h" + +#define SET_ETHERNET_PACKET_FILTER (0x43) + + +extern uint8_t cdc_ecm_process(void); +extern uint8_t ecm_send(uint8_t * senddata, uint16_t sendlen, uint8_t led); +extern void cdc_ecm_set_ethernet_packet_filter(void); +extern void cdc_ecm_configure_endpoints(); +extern void cdc_ecm_set_active(uint8_t value); + +#endif // __CDC_ECM_H__ \ No newline at end of file diff --git a/cpu/avr/dev/usb/rndis/cdc_eem.c b/cpu/avr/dev/usb/rndis/cdc_eem.c new file mode 100644 index 000000000..7b98702f0 --- /dev/null +++ b/cpu/avr/dev/usb/rndis/cdc_eem.c @@ -0,0 +1,296 @@ +#include "cdc_eem.h" +#include "contiki.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" +#include "rndis/rndis_task.h" +#include "rndis/rndis_protocol.h" +#include "uip.h" +#include "sicslow_ethernet.h" +#include + +#include +#include + +#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) +#define PRINTF printf +#define PRINTF_P printf_P + +extern uint8_t usb_eth_data_buffer[64]; + + +//_____ M A C R O S ________________________________________________________ + + +#define EEMCMD_ECHO 0x00 ///bmEEMCmd Echo +#define EEMCMD_ECHO_RESPONSE 0x01 ///bmEEMCmd Echo Response +#define EEMCMD_SUSPEND_HINT 0x02 ///bmEEMCmd Suspend Hint +#define EEMCMD_RESPONSE_HINT 0x03 ///bmEEMCmd Response Hint +#define EEMCMD_RESPONSE_COMPLETE_HINT 0x04 ///bmEEMCmd Response Complete Hint +#define EEMCMD_TICKLE 0x05 ///bmEEMCmd Tickle + + +void cdc_eem_configure_endpoints() { + usb_configure_endpoint(TX_EP, \ + TYPE_BULK, \ + DIRECTION_IN, \ + SIZE_64, \ + TWO_BANKS, \ + NYET_ENABLED); + + usb_configure_endpoint(RX_EP, \ + TYPE_BULK, \ + DIRECTION_OUT, \ + SIZE_64, \ + TWO_BANKS, \ + NYET_ENABLED); + Usb_reset_endpoint(TX_EP); + Usb_reset_endpoint(RX_EP); +} + +void cdc_eem_process(void) { + uint16_t datalength; + uint8_t bytecounter, headercounter; + uint16_t i; + +#ifdef USB_ETH_HOOK_INIT + static uint8_t doInit = 1; + if (doInit) { + USB_ETH_HOOK_INIT(); + doInit = 0; + } +#endif + + //Connected! + Led0_on(); + + Usb_select_endpoint(RX_EP); + + //If we have data and a free buffer + if(Is_usb_receive_out() && (uip_len == 0)) { + + //Read how much (endpoint only stores up to 64 bytes anyway) + bytecounter = Usb_byte_counter_8(); + + //EEM uses 2 bytes as a header + headercounter = 2; + + uint8_t fail = 0; + + //Hmm.. what's going on here? + if (bytecounter < headercounter) { + Usb_ack_receive_out(); + //TODO CO done = 1; + } + + //Read EEM Header + i = 0; + while (headercounter) { + usb_eth_data_buffer[i] = Usb_read_byte(); + bytecounter--; + headercounter--; + i++; + } + + //Order is LSB/MSB, so MSN is in usb_eth_data_buffer[1] + //Bit 15 indicates command packet when set + if (usb_eth_data_buffer[1] & 0x80) { + //not a data payload + datalength = 0; + } else { + //'0' indicates data packet + //Length is lower 14 bits + datalength = usb_eth_data_buffer[0] | ((usb_eth_data_buffer[1] & 0x3F) << 8); + } + + /* EEM Command Packet */ + if ((datalength == 0) && (fail == 0)) + { + uint8_t command; + uint16_t echoLength; + + //Strip command off + command = usb_eth_data_buffer[1] & 0x38; + command = command >> 3; + + //Decode command type + switch (command) + { + /* Echo Request */ + case EEMCMD_ECHO: + + //Get echo length + echoLength = (usb_eth_data_buffer[1] & 0x07) << 8; //MSB + echoLength |= usb_eth_data_buffer[0]; //LSB + + //TODO: everything. oops. + + break; + + /* Everything else: Whatever. */ + case EEMCMD_ECHO_RESPONSE: + case EEMCMD_SUSPEND_HINT: + case EEMCMD_RESPONSE_HINT: + case EEMCMD_RESPONSE_COMPLETE_HINT: + case EEMCMD_TICKLE: + break; + + default: break; + } + } + /* EEM Data Packet */ + else if (datalength && (fail == 0)) + { + //Looks like we've got a live one +#ifdef USB_ETH_HOOK_RX_START + USB_ETH_HOOK_RX_START(); +#endif + + uint16_t bytes_received = 0; + uint16_t dataleft = datalength; + U8 * buffer = uip_buf; + + while(dataleft) + { + *buffer++ = Usb_read_byte(); + + dataleft--; + bytecounter--; + bytes_received++; + + //Check if endpoint is done but we are expecting more data + if ((bytecounter == 0) && (dataleft)) + { + //ACK previous data + Usb_ack_receive_out(); + + //Wait for new data + while (!Is_usb_receive_out()); + + //Get new data + bytecounter = Usb_byte_counter_8(); + + //ZLP? + if (bytecounter == 0) + { + //Incomplete!! + break; + } + } + } + + //Ack final data packet + Usb_ack_receive_out(); + +#ifdef USB_ETH_HOOK_RX_END + USB_ETH_HOOK_RX_END(); +#endif + + //Packet has CRC, nobody wants that garbage + datalength -= 4; + + //Send data over RF or to local stack + if(datalength <= USB_ETH_MTU) { + USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,datalength); + } else { + USB_ETH_HOOK_RX_ERROR("Oversized packet"); + } + } //if (datalength) + } //if(Is_usb_receive_out() && (uip_len == 0)) +} + + +/** + \brief Send a single ethernet frame using EEM + */ +uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) +{ + //Make a header + uint8_t header[2]; + + //Fake CRC! Add 4 to length for CRC + sendlen += 4; + header[0] = (sendlen >> 8) & 0x3f; + header[1] = sendlen & 0xff; + + //We send CRC seperatly.. + sendlen -= 4; + + //Send Data + Usb_select_endpoint(TX_EP); + //Usb_send_in(); + + //Wait for ready + if(usb_endpoint_wait_for_write_enabled()!=0) { + USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); + return 0; + } + +#ifdef USB_ETH_HOOK_TX_START + USB_ETH_HOOK_TX_START(); +#endif + + //Send header (LSB then MSB) + Usb_write_byte(header[1]); + Usb_write_byte(header[0]); + + //Send packet + while(sendlen) { + Usb_write_byte(*senddata); + senddata++; + sendlen--; + + //If endpoint is full, send data in + //And then wait for data to transfer + if (!Is_usb_write_enabled()) { + Usb_send_in(); + + if(usb_endpoint_wait_for_write_enabled()!=0) { + USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); + return 0; + } + } + + } + + //CRC = 0xdeadbeef + //Linux kernel 2.6.31 needs 0xdeadbeef in wrong order, + //like this: uint8_t crc[4] = {0xef, 0xbe, 0xad, 0xde}; + //This is fixed in 2.6.32 to the correct order (0xde, 0xad, 0xbe, 0xef) + uint8_t crc[4] = {0xde, 0xad, 0xbe, 0xef}; + + sendlen = 4; + uint8_t i = 0; + + //Send fake CRC + while(sendlen) { + Usb_write_byte(crc[i]); + i++; + sendlen--; + + //If endpoint is full, send data in + //And then wait for data to transfer + if (!Is_usb_write_enabled()) { + Usb_send_in(); + if(usb_endpoint_wait_for_write_enabled()!=0) { + USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); + return 0; + } + } + } + + //Send last data in - also handles sending a ZLP if needed + Usb_send_in(); + +#ifdef USB_ETH_HOOK_TX_END + USB_ETH_HOOK_TX_END(); +#endif + + //Wait for ready + if(usb_endpoint_wait_for_IN_ready()!=0) { + USB_ETH_HOOK_TX_ERROR("Timeout: IN ready"); + return 0; + } + + return 1; +} diff --git a/cpu/avr/dev/usb/rndis/cdc_eem.h b/cpu/avr/dev/usb/rndis/cdc_eem.h new file mode 100644 index 000000000..1f7c8ae49 --- /dev/null +++ b/cpu/avr/dev/usb/rndis/cdc_eem.h @@ -0,0 +1,12 @@ + +#ifndef __CDC_EEM_H__ +#define __CDC_EEM_H__ + +#include "contiki.h" +#include + +extern void cdc_eem_process(void); +extern uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led); +extern void cdc_eem_configure_endpoints(); + +#endif // __CDC_EEM_H__ diff --git a/cpu/avr/dev/usb/rndis/rndis.c b/cpu/avr/dev/usb/rndis/rndis.c index af0c81a28..b49e0674d 100644 --- a/cpu/avr/dev/usb/rndis/rndis.c +++ b/cpu/avr/dev/usb/rndis/rndis.c @@ -58,6 +58,7 @@ RNDIS Status Information: //_____ I N C L U D E S ____________________________________________________ +#include #include "radio.h" #include "contiki.h" #include "config.h" @@ -65,12 +66,18 @@ RNDIS Status Information: #include "usb_descriptors.h" #include "usb_specific_request.h" #include "rndis/rndis_protocol.h" +#include "rndis/rndis_task.h" #include "uip.h" #include "serial/uart_usb_lib.h" #include "sicslow_ethernet.h" #include #include +#include +#include +#include + + //_____ M A C R O S ________________________________________________________ //_____ D E F I N I T I O N ________________________________________________ @@ -80,14 +87,10 @@ RNDIS Status Information: extern PGM_VOID_P pbuffer; extern U8 data_to_transfer; -//NB: If you change the OID list be sure to update this!!! -//#define OID_LIST_LENGTH 50 -#define OID_LIST_LENGTH 35 - /** * \brief List of supported RNDIS OID's */ -prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = { +prog_uint32_t OIDSupportedList[] = { /* Required General */ OID_GEN_SUPPORTED_LIST , OID_GEN_HARDWARE_STATUS , @@ -128,7 +131,7 @@ prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = { /*802.11 OID's not fully implemented yet. Hence do not say we support them */ -#ifdef DONOTEVERDEFINETHISORBADSTUFFHAPPENS +#if USB_ETH_EMULATE_WIFI /* 802.11 OIDs */ OID_802_11_BSSID , OID_802_11_SSID , @@ -156,18 +159,17 @@ prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = { OID_PNP_ENABLE_WAKE_UP , OID_PNP_ADD_WAKE_UP_PATTERN , OID_PNP_REMOVE_WAKE_UP_PATTERN +}; - }; +#define OID_LIST_LENGTH sizeof(OIDSupportedList)/sizeof(*OIDSupportedList) rndis_state_t rndis_state; -rndis_stat_t rndis_stat; +usb_eth_stat_t usb_eth_stat; uint8_t schedule_interrupt = 0; -uint64_t rndis_ethernet_addr = 0x203478928323ULL; - //_____ D E C L A R A T I O N ______________________________________________ @@ -188,7 +190,7 @@ U8 data_to_send = 0x00; * * \return True on success, false on failure. */ -uint8_t send_encapsulated_command(uint16_t wLength) +uint8_t rndis_send_encapsulated_command(uint16_t wLength) { U8 i = 0; @@ -200,12 +202,6 @@ uint8_t send_encapsulated_command(uint16_t wLength) if (wLength > ENC_BUF_SIZE) wLength = ENC_BUF_SIZE; - //For debugging: this shouldn't happen, just checked it didn't - //if (data_to_send) { - // while(1); - //} - - //Read in all the bytes... uint8_t nb_counter; @@ -256,9 +252,13 @@ uint8_t send_encapsulated_command(uint16_t wLength) m->MinorVersion = RNDIS_MAJOR_VERSION; m->Status = RNDIS_STATUS_SUCCESS; m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; +#if USB_ETH_EMULATE_WIFI + m->Medium = NDIS_MEDIUM_WIRELESS_LAN; +#else m->Medium = RNDIS_MEDIUM_802_3; +#endif // USB_ETH_EMULATE_WIFI m->MaxPacketsPerTransfer = 1; - m->MaxTransferSize = 1338; /* Space for 1280 IP buffer, Ethernet Header, + m->MaxTransferSize = USB_ETH_MTU + 58; /* Space for 1280 IP buffer, Ethernet Header, RNDIS messages */ m->PacketAlignmentFactor = 3; m->AfListOffset = 0; @@ -353,7 +353,9 @@ void rndis_send_interrupt(void) uint32_t oid_packet_filter = 0x0000000; +#if USB_ETH_EMULATE_WIFI uint16_t panid = 0xbaad; +#endif /** * \brief Function to handle a RNDIS "QUERY" command in the encapsulated_buffer @@ -392,15 +394,20 @@ void rndis_query_process(void) case OID_GEN_MEDIA_SUPPORTED: case OID_GEN_MEDIA_IN_USE: - *INFBUF = NDIS_MEDIUM_802_3; /* NDIS_MEDIUM_WIRELESS_LAN instead? */ + case OID_GEN_PHYSICAL_MEDIUM: +#if USB_ETH_EMULATE_WIFI + *INFBUF = NDIS_MEDIUM_WIRELESS_LAN; +#else + *INFBUF = NDIS_MEDIUM_802_3; +#endif break; case OID_GEN_MAXIMUM_FRAME_SIZE: - *INFBUF = (uint32_t) 1280; //1280 //102; /* Assume 25 octet header on 15.4 */ + *INFBUF = (uint32_t) USB_ETH_MTU-14; //1280 //102; /* Assume 25 octet header on 15.4 */ break; case OID_GEN_LINK_SPEED: - *INFBUF = (uint32_t) 100; /* in 100 bytes/sec units.. this is kinda a lie */ + *INFBUF = (uint32_t) 250000/100; /* in 100 bytes/sec units.. this is kinda a lie */ break; case OID_GEN_TRANSMIT_BLOCK_SIZE: @@ -422,57 +429,35 @@ void rndis_query_process(void) break; case OID_GEN_MAXIMUM_TOTAL_SIZE: - *INFBUF = (uint32_t) 1300; //127; + *INFBUF = (uint32_t) USB_ETH_MTU; //127; break; case OID_GEN_MEDIA_CONNECT_STATUS: - *INFBUF = NDIS_MEDIA_STATE_CONNECTED; + *INFBUF = usb_eth_is_active?NDIS_MEDIA_STATE_CONNECTED:NDIS_MEDIA_STATE_DISCONNECTED; break; case OID_GEN_VENDOR_DRIVER_VERSION: *INFBUF = 0x00001000; break; - case OID_GEN_PHYSICAL_MEDIUM: - *INFBUF = NDIS_MEDIUM_802_3; /*NDIS_MEDIUM_WIRELESS_LAN;*/ - break; case OID_GEN_CURRENT_LOOKAHEAD: - *INFBUF = (uint32_t) 1280; //102; + *INFBUF = (uint32_t) USB_ETH_MTU-14; //102; + +// case OID_GEN_RNDIS_CONFIG_PARAMETER: +// break; /******* 802.3 (Ethernet) *******/ /*The address of the NIC encoded in the hardware.*/ case OID_802_3_PERMANENT_ADDRESS: - - //Clear unused bytes - *(INFBUF + 1) = 0; - - //Set address - *((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5); - *((uint8_t *)INFBUF + 1) = *(((uint8_t * ) &rndis_ethernet_addr) + 4); - *((uint8_t *)INFBUF + 2) = *(((uint8_t * ) &rndis_ethernet_addr) + 3); - *((uint8_t *)INFBUF + 3) = *(((uint8_t * ) &rndis_ethernet_addr) + 2); - *((uint8_t *)INFBUF + 4) = *(((uint8_t * ) &rndis_ethernet_addr) + 1); - *((uint8_t *)INFBUF + 5) = *(((uint8_t * ) &rndis_ethernet_addr) + 0); - - - /*4+2 = 6 Bytes of eth address */ - c->InformationBufferLength += 2; - break; - - /*The address the NIC is currently using.*/ case OID_802_3_CURRENT_ADDRESS: + //Clear unused bytes *(INFBUF + 1) = 0; - //Set address - *((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5); - *((uint8_t *)INFBUF + 1) = *(((uint8_t * ) &rndis_ethernet_addr) + 4); - *((uint8_t *)INFBUF + 2) = *(((uint8_t * ) &rndis_ethernet_addr) + 3); - *((uint8_t *)INFBUF + 3) = *(((uint8_t * ) &rndis_ethernet_addr) + 2); - *((uint8_t *)INFBUF + 4) = *(((uint8_t * ) &rndis_ethernet_addr) + 1); - *((uint8_t *)INFBUF + 5) = *(((uint8_t * ) &rndis_ethernet_addr) + 0); + //get address + usb_eth_get_mac_address((uint8_t*)INFBUF); /*4+2 = 6 Bytes of eth address */ c->InformationBufferLength += 2; @@ -495,20 +480,14 @@ void rndis_query_process(void) /* Frames received with alignment error */ case OID_802_3_RCV_ERROR_ALIGNMENT: - *INFBUF = 0; - break; - /* Frames transmitted with one collision */ case OID_802_3_XMIT_ONE_COLLISION: - *INFBUF = 0; - break; - /* Frames transmitted with more than one collision */ case OID_802_3_XMIT_MORE_COLLISIONS: *INFBUF = 0; break; - +#if USB_ETH_EMULATE_WIFI /*** 802.11 OIDs ***/ case OID_802_11_BSSID: *INFBUF = (uint32_t)panid; @@ -543,27 +522,28 @@ void rndis_query_process(void) case OID_802_11_WEP_STATUS: case OID_802_11_AUTHENTICATION_MODE: break; +#endif //USB_ETH_EMULATE_WIFI /*** Statistical ***/ /* Frames transmitted without errors */ case OID_GEN_XMIT_OK: - *INFBUF = rndis_stat.txok; + *INFBUF = usb_eth_stat.txok; break; /* Frames received without errors */ case OID_GEN_RCV_OK: - *INFBUF = rndis_stat.rxok; + *INFBUF = usb_eth_stat.rxok; break; /* Frames received with errors */ case OID_GEN_RCV_ERROR: - *INFBUF = rndis_stat.rxbad; + *INFBUF = usb_eth_stat.rxbad; break; /* Frames transmitted with errors */ case OID_GEN_XMIT_ERROR: - *INFBUF = rndis_stat.txbad; + *INFBUF = usb_eth_stat.txbad; break; /* Frames dropped due to lack of buffer space */ @@ -617,9 +597,21 @@ void rndis_query_process(void) #define CFGBUF ((rndis_config_parameter_t *) INFBUF) #define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset) #define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset) - +#define PARMVALUELENGTH CFGBUF->ParameterValueLength #define PARM_NAME_LENGTH 25 /* Maximum parameter name length */ +bool +rndis_handle_config_parm(const char* parmname,const uint8_t* parmvalue,size_t parmlength) { + if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) { + if (parmvalue[0] == '0') { + usbstick_mode.raw = 0; + } else { + usbstick_mode.raw = 1; + } + } + +} + /** * \brief Function to deal with a RNDIS "SET" command present in the * encapsulated_buffer @@ -664,13 +656,7 @@ void rndis_set_process(void) Parameter type: single octet Parameter values: '0' = disabled, '1' = enabled */ - if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) { - if (*PARMVALUE == '0') { - usbstick_mode.raw = 0; - } else { - usbstick_mode.raw = 1; - } - } + rndis_handle_config_parm(parmname,PARMVALUE,PARMVALUELENGTH); break; @@ -700,6 +686,7 @@ void rndis_set_process(void) case OID_802_3_MULTICAST_LIST: break; +#if USB_ETH_EMULATE_WIFI /* Mandatory 802.11 OIDs */ case OID_802_11_BSSID: panid = *INFBUF; @@ -708,6 +695,7 @@ void rndis_set_process(void) case OID_802_11_SSID: break; //TODO: rest of 802.11 +#endif // USB_ETH_EMULATE_WIFI /* Power Managment: fails for now */ case OID_PNP_ADD_WAKE_UP_PATTERN: @@ -743,7 +731,7 @@ void rndis_set_process(void) * the "SEND ENCAPSULATED COMMAND" message, which will trigger * and interrupt on the host so it knows data is ready. */ -uint8_t get_encapsulated_command(void) +uint8_t rndis_get_encapsulated_command(void) { U8 nb_byte, zlp, i; @@ -828,6 +816,261 @@ uint8_t rndis_send_status(rndis_Status_t stat) return 0; } +void rndis_configure_endpoints() { + usb_configure_endpoint(INT_EP, \ + TYPE_INTERRUPT, \ + DIRECTION_IN, \ + SIZE_8, \ + ONE_BANK, \ + NYET_ENABLED); + usb_configure_endpoint(TX_EP, \ + TYPE_BULK, \ + DIRECTION_IN, \ + SIZE_64, \ + TWO_BANKS, \ + NYET_ENABLED); + + usb_configure_endpoint(RX_EP, \ + TYPE_BULK, \ + DIRECTION_OUT, \ + SIZE_64, \ + TWO_BANKS, \ + NYET_ENABLED); + Usb_reset_endpoint(INT_EP); + Usb_reset_endpoint(TX_EP); + Usb_reset_endpoint(RX_EP); +} + + +extern char usb_busy; +extern uint8_t usb_eth_data_buffer[64]; +#define PBUF ((rndis_data_packet_t *) usb_eth_data_buffer) + + +uint8_t rndis_process(void) +{ + uint8_t bytecounter, headercounter; + uint16_t i, dataoffset; + + if(rndis_state != rndis_data_initialized) { //Enumeration processs OK ? + return 0; + } + +#ifdef USB_ETH_HOOK_INIT + static uint8_t doInit = 1; + if (doInit) { + USB_ETH_HOOK_INIT(); + doInit = 0; + } +#endif + + //Connected! + Led0_on(); + + Usb_select_endpoint(RX_EP); + + //If we have data and a free buffer + if(Is_usb_receive_out() && (uip_len == 0)) { + + //Read how much (endpoint only stores up to 64 bytes anyway) + bytecounter = Usb_byte_counter_8(); + + //Try and read the header in + headercounter = sizeof(rndis_data_packet_t); + + uint8_t fail = 0; + + //Hmm.. what's going on here + if (bytecounter < headercounter) { + Usb_ack_receive_out(); + fail = 1; + } + + i = 0; + while (headercounter) { + usb_eth_data_buffer[i] = Usb_read_byte(); + bytecounter--; + headercounter--; + i++; + } + + //This is no good. Probably lost syncronization... just drop it for now + if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) { + Usb_ack_receive_out(); + fail = 1; + } + + //802.3 does not have OOB data, and we don't care about per-packet data + //so that just leave regular packet data... + if (PBUF->DataLength && (fail == 0)) { + + //Looks like we've got a live one +#ifdef USB_ETH_HOOK_RX_START + USB_ETH_HOOK_RX_START(); +#endif + + //Get offset + dataoffset = PBUF->DataOffset; + + //Make it offset from start of message, not DataOffset field + dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t)); + + //Subtract what we already took + dataoffset -= sizeof(rndis_data_packet_t); + + //Clear this flag + Usb_ack_nak_out(); + + //Read to the start of data + while(dataoffset) { + Usb_read_byte(); + dataoffset--; + bytecounter--; + + //If endpoint is done + if (bytecounter == 0) { + + Usb_ack_receive_out(); + + + //Wait for new data + while (!Is_usb_receive_out() && (!Is_usb_receive_nak_out())); + + //Check for NAK + // TODO: darco: What in the world is this for? + if (Is_usb_receive_nak_out()) { + Usb_ack_nak_out(); + break; + } + + bytecounter = Usb_byte_counter_8(); + + //ZLP? + if (bytecounter == 0) + break; + } + + } + + //Read the data itself in + uint8_t * uipdata = uip_buf; + uint16_t datalen = PBUF->DataLength; + + while(datalen) { + *uipdata++ = Usb_read_byte(); + datalen--; + bytecounter--; + + //If endpoint is done + if (bytecounter == 0) { + //Might be everything we need! + if (datalen) { + Usb_ack_receive_out(); + //Wait for new data + if(usb_endpoint_wait_for_receive_out()!=0) { + USB_ETH_HOOK_RX_ERROR("Timeout: receive out"); + goto bail; + } + bytecounter = Usb_byte_counter_8(); + } + } + + } + + //Ack final data packet + Usb_ack_receive_out(); + +#ifdef USB_ETH_HOOK_RX_END + USB_ETH_HOOK_RX_END(); +#endif + + //Send data over RF or to local stack + if(PBUF->DataLength <= USB_ETH_MTU) { + USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,PBUF->DataLength); + } else { + USB_ETH_HOOK_RX_ERROR("Oversized packet"); + } + } //if (PBUF->DataLength) + } +bail: + return 1; +} + +/** + \brief Send data over RNDIS interface, data is in uipbuf and length is uiplen + */ +uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) +{ + + + uint16_t i; + + //Setup Header + PBUF->MessageType = REMOTE_NDIS_PACKET_MSG; + PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t); + PBUF->DataLength = sendlen; + PBUF->OOBDataLength = 0; + PBUF->OOBDataOffset = 0; + PBUF->NumOOBDataElements = 0; + PBUF->PerPacketInfoOffset = 0; + PBUF->PerPacketInfoLength = 0; + PBUF->DeviceVcHandle = 0; + PBUF->Reserved = 0; + PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength; + + //Send Data + Usb_select_endpoint(TX_EP); + Usb_send_in(); + + //Wait for ready + if(usb_endpoint_wait_for_write_enabled()!=0) { + USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); + return 0; + } + +#ifdef USB_ETH_HOOK_TX_START + USB_ETH_HOOK_TX_START(); +#endif + + //Setup first part of transfer... + for(i = 0; i < sizeof(rndis_data_packet_t); i++) { + Usb_write_byte(usb_eth_data_buffer[i]); + } + + //Send packet + while(sendlen) { + Usb_write_byte(*senddata); + senddata++; + sendlen--; + + //If endpoint is full, send data in + //And then wait for data to transfer + if (!Is_usb_write_enabled()) { + Usb_send_in(); + + if(usb_endpoint_wait_for_write_enabled()!=0) { + USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); + return 0; + } + } + + } + + Usb_send_in(); + +#ifdef USB_ETH_HOOK_TX_END + USB_ETH_HOOK_TX_END(); +#endif + + //Wait for ready + if(usb_endpoint_wait_for_IN_ready()!=0) { + USB_ETH_HOOK_TX_ERROR("Timeout: IN ready"); + return 0; + } + + return 1; +} + /****************** Radio Interface ****************/ @@ -837,15 +1080,11 @@ uint8_t rndis_send_status(rndis_Status_t stat) */ void rndis_packetFilter(uint32_t newfilter) { -#if !RF230BB if (newfilter & NDIS_PACKET_TYPE_PROMISCUOUS) { - rxMode = RX_ON; - radio_set_trx_state(RX_ON); + USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true); } else { - rxMode = RX_AACK_ON; - radio_set_trx_state(RX_AACK_ON); + USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false); } -#endif } /** @} */ diff --git a/cpu/avr/dev/usb/rndis/rndis_protocol.h b/cpu/avr/dev/usb/rndis/rndis_protocol.h index 201521440..ee88f6e3c 100644 --- a/cpu/avr/dev/usb/rndis/rndis_protocol.h +++ b/cpu/avr/dev/usb/rndis/rndis_protocol.h @@ -303,22 +303,23 @@ typedef struct{ uint32_t rxok; uint32_t txbad; uint32_t rxbad; - } rndis_stat_t; + } usb_eth_stat_t; -extern rndis_stat_t rndis_stat; +extern usb_eth_stat_t usb_eth_stat; extern rndis_state_t rndis_state; extern uint8_t schedule_interrupt; -extern uint64_t rndis_ethernet_addr; - -uint8_t send_encapsulated_command(uint16_t wLength); -uint8_t get_encapsulated_command(void); +uint8_t rndis_send_encapsulated_command(uint16_t wLength); +uint8_t rndis_get_encapsulated_command(void); void rndis_send_interrupt(void); void rndis_query_process(void); void rndis_set_process(void); uint8_t rndis_send_status(rndis_Status_t stat); +uint8_t rndis_process(void); +uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led); +extern void rndis_configure_endpoints(); #endif //_RNDIS_H diff --git a/cpu/avr/dev/usb/rndis/rndis_task.c b/cpu/avr/dev/usb/rndis/rndis_task.c index 37c60105f..e2088ec36 100644 --- a/cpu/avr/dev/usb/rndis/rndis_task.c +++ b/cpu/avr/dev/usb/rndis/rndis_task.c @@ -59,6 +59,9 @@ #include #include +#include "rndis/cdc_ecm.h" +#include "rndis/cdc_eem.h" + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) #define PRINTF printf #define PRINTF_P printf_P @@ -66,12 +69,6 @@ //_____ M A C R O S ________________________________________________________ -#define EEMCMD_ECHO 0x00 ///bmEEMCmd Echo -#define EEMCMD_ECHO_RESPONSE 0x01 ///bmEEMCmd Echo Response -#define EEMCMD_SUSPEND_HINT 0x02 ///bmEEMCmd Suspend Hint -#define EEMCMD_RESPONSE_HINT 0x03 ///bmEEMCmd Response Hint -#define EEMCMD_RESPONSE_COMPLETE_HINT 0x04 ///bmEEMCmd Response Complete Hint -#define EEMCMD_TICKLE 0x05 ///bmEEMCmd Tickle @@ -84,436 +81,210 @@ #define RNDIS_TIMEOUT_DETACH 900 #define RNDIS_TIMEOUT_ATTACH 1000 -#define PBUF ((rndis_data_packet_t *) data_buffer) +#define PBUF ((rndis_data_packet_t *) usb_eth_data_buffer) + +//! Temp data buffer when adding RNDIS headers +uint8_t usb_eth_data_buffer[64]; + +uint64_t usb_ethernet_addr = 0x010000000002ULL; //_____ D E C L A R A T I O N S ____________________________________________ -uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led); -uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led); //! Timers for LEDs uint8_t led1_timer, led2_timer; -//! Temp data buffer when adding RNDIS headers -uint8_t data_buffer[64]; - -//! Usb is busy with RNDIS -char usb_busy = 0; +uint8_t usb_eth_is_active = 1; -static struct etimer et; -static struct timer flood_timer; +uint8_t usb_eth_packet_is_available() { + Usb_select_endpoint(RX_EP); + return Is_usb_read_enabled(); +} -static uint8_t doInit = 1; -extern uint8_t fingerPresent; +uint8_t usb_eth_ready_for_next_packet() { +#ifdef USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET + return USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET(); +#else + return 1; +#endif -PROCESS(rndis_process, "RNDIS process"); + return 1; +} + +void rxtx_led_update(void) +{ + // turn off LED's if necessary + if (led1_timer) { + led1_timer--; + if(led1_timer&(1<<2)) + Led1_on(); + else + Led1_off(); + } + else + Led1_off(); + + if (led2_timer) { + led2_timer--; + if(led2_timer&(1<<2)) + Led2_on(); + else + Led2_off(); + } + else + Led2_off(); +} + +/** + @brief This will enable the RX_START LED for a period +*/ +void rx_start_led(void) +{ + led1_timer|=(1<<3); + if(((led1_timer-1)&(1<<2))) + Led1_on(); +} + +/** + @brief This will enable the TRX_END LED for a period +*/ +void tx_end_led(void) +{ + led2_timer|=(1<<3); + if(((led2_timer-1)&(1<<2))) + Led1_on(); +} + +#if USB_ETH_CONF_MASS_STORAGE_FALLBACK +static void +usb_eth_setup_timeout_fallback_check() { + extern uint8_t fingerPresent; + /* Device is Enumerated but RNDIS not loading. We might + have a system that does not support IAD (winXP). If so + count the timeout then switch to just network interface. */ + static uint16_t iad_fail_timeout, rndis_fail_timeout; + if (usb_mode == rndis_debug) { + //If we have timed out, detach + if (iad_fail_timeout == IAD_TIMEOUT_DETACH) { + + //Failed - BUT we are using "reverse logic", hence we force device + //into this mode. This is used to allow Windows Vista have time to + //install the drivers + if (fingerPresent && (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) { + iad_fail_timeout = 0; + } else { + stdout = NULL; + Usb_detach(); + doInit = 1; //Also mark system as needing intilizing + } + + //Then wait a few before re-attaching + } else if (iad_fail_timeout == IAD_TIMEOUT_ATTACH) { + + if (fingerPresent) { + usb_mode = mass_storage; + } else { + usb_mode = rndis_only; + } + Usb_attach(); + } + + //Increment timeout when device is not initializing, OR we have already detached, + //OR the user had their finger on the device, indicating a reverse of logic + if ( ( (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) || + (iad_fail_timeout > IAD_TIMEOUT_DETACH) || + (fingerPresent) ) { + iad_fail_timeout++; + } else { + iad_fail_timeout = 0; + } + } //usb_mode == rndis_debug + + + /* Device is Enumerated but RNDIS STIL not loading. We just + have RNDIS interface, so obviously no drivers on target. + Just go ahead and mount ourselves as mass storage... */ + if (usb_mode == rndis_only) { + //If we have timed out, detach + if (rndis_fail_timeout == RNDIS_TIMEOUT_DETACH) { + Usb_detach(); + //Then wait a few before re-attaching + } else if (rndis_fail_timeout == RNDIS_TIMEOUT_ATTACH) { + usb_mode = mass_storage; + Usb_attach(); + } + + //Increment timeout when device is not initializing, OR we are already + //counting to detach + if ( ( (rndis_state != rndis_data_initialized)) || + (rndis_fail_timeout > RNDIS_TIMEOUT_DETACH) ) { + rndis_fail_timeout++; + } else { + rndis_fail_timeout = 0; + } + }//usb_mode == rnids_only +} +#endif + +PROCESS(usb_eth_process, "USB Ethernet process"); /** * \brief RNDIS Process * * This is the link between USB and the "good stuff". In this routine data - * is received and processed by RNDIS + * is received and processed by RNDIS, CDC-ECM, or CDC-EEM */ -PROCESS_THREAD(rndis_process, ev, data_proc) +PROCESS_THREAD(usb_eth_process, ev, data_proc) { + static struct etimer et; PROCESS_BEGIN(); - uint8_t bytecounter, headercounter; - uint16_t i, dataoffset; - clock_time_t timediff; - clock_time_t thetime; while(1) { + rxtx_led_update(); - // turn off LED's if necessary - if (led1_timer) led1_timer--; - else Led1_off(); - if (led2_timer) led2_timer--; - else Led2_off(); - - /* Device is Enumerated but RNDIS not loading. We might - have a system that does not support IAD (winXP). If so - count the timeout then switch to just network interface. */ -#if 0 -static uint16_t iad_fail_timeout, rndis_fail_timeout; - if (usb_mode == rndis_debug) { - //If we have timed out, detach - if (iad_fail_timeout == IAD_TIMEOUT_DETACH) { - - //Failed - BUT we are using "reverse logic", hence we force device - //into this mode. This is used to allow Windows Vista have time to - //install the drivers - if (fingerPresent && (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) { - iad_fail_timeout = 0; - } else { - stdout = NULL; - Usb_detach(); - doInit = 1; //Also mark system as needing intilizing - } - - //Then wait a few before re-attaching - } else if (iad_fail_timeout == IAD_TIMEOUT_ATTACH) { - - if (fingerPresent) { - usb_mode = mass_storage; - } else { - usb_mode = rndis_only; - } - Usb_attach(); - } - - //Increment timeout when device is not initializing, OR we have already detached, - //OR the user had their finger on the device, indicating a reverse of logic - if ( ( (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) || - (iad_fail_timeout > IAD_TIMEOUT_DETACH) || - (fingerPresent) ) { - iad_fail_timeout++; - } else { - iad_fail_timeout = 0; - } - } //usb_mode == rndis_debug - - - /* Device is Enumerated but RNDIS STIL not loading. We just - have RNDIS interface, so obviously no drivers on target. - Just go ahead and mount ourselves as mass storage... */ - if (usb_mode == rndis_only) { - //If we have timed out, detach - if (rndis_fail_timeout == RNDIS_TIMEOUT_DETACH) { - Usb_detach(); - //Then wait a few before re-attaching - } else if (rndis_fail_timeout == RNDIS_TIMEOUT_ATTACH) { - usb_mode = mass_storage; - Usb_attach(); - } - - //Increment timeout when device is not initializing, OR we are already - //counting to detach - if ( ( (rndis_state != rndis_data_initialized)) || - (rndis_fail_timeout > RNDIS_TIMEOUT_DETACH) ) { - rndis_fail_timeout++; - } else { - rndis_fail_timeout = 0; - } - }//usb_mode == rnids_only +#if USB_ETH_CONF_MASS_STORAGE_FALLBACK + usb_eth_setup_timeout_fallback_check(); #endif - - - if(rndis_state == rndis_data_initialized) //Enumeration processs OK ? - { - if (doInit) { - //start flood timer - timer_set(&flood_timer, CLOCK_SECOND / 5); - - mac_ethernetSetup(); - doInit = 0; - } - - //Connected! - Led0_on(); - - Usb_select_endpoint(RX_EP); - - //If we have data and a free buffer - if(Is_usb_receive_out() && (uip_len == 0)) { - - //TODO: Fix this some better way - //If you need a delay in RNDIS to slow down super-fast sending, insert it here - //Also mark the USB as "in use" - - //This is done as "flood control" by only allowing one IP packet per time limit - thetime = clock_time(); - - timediff = thetime - flood_timer.start; - - //Oops, timer wrapped! Just ignore it for now - if (thetime < flood_timer.start) { - timediff = flood_timer.interval; - } - - - //If timer not yet expired - //if (timediff < flood_timer.interval) { - if (!timer_expired(&flood_timer)) { - //Wait until timer expiers - usb_busy = 1; - etimer_set(&et, flood_timer.interval - timediff); -//Try commenting out the next line if Jackdaw stops RF transmission in Windows after a 5 minute idle period - dak - PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); - - //Reselect endpoint in case we lost it - Usb_select_endpoint(RX_EP); - usb_busy = 0; - } - - - //Restart flood timer - timer_restart(&flood_timer); - - //Read how much (endpoint only stores up to 64 bytes anyway) - bytecounter = Usb_byte_counter_8(); - - //Try and read the header in - headercounter = sizeof(rndis_data_packet_t); - - uint8_t fail = 0; - - //Hmm.. what's going on here - if (bytecounter < headercounter) { - Usb_ack_receive_out(); - fail = 1; - } - - i = 0; - while (headercounter) { - data_buffer[i] = Usb_read_byte(); - bytecounter--; - headercounter--; - i++; - } - - //This is no good. Probably lost syncronization... just drop it for now - if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) { - Usb_ack_receive_out(); - fail = 1; - } - - //802.3 does not have OOB data, and we don't care about per-packet data - //so that just leave regular packet data... - if (PBUF->DataLength && (fail == 0)) { - - //Looks like we've got a live one - rx_start_led(); - - - //Get offset - dataoffset = PBUF->DataOffset; - - //Make it offset from start of message, not DataOffset field - dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t)); - - //Subtract what we already took - dataoffset -= sizeof(rndis_data_packet_t); - - //Clear this flag - Usb_ack_nak_out(); - - //Read to the start of data - while(dataoffset) { - Usb_read_byte(); - dataoffset--; - bytecounter--; - - //If endpoint is done - if (bytecounter == 0) { - - Usb_ack_receive_out(); - - - //Wait for new data - while (!Is_usb_receive_out() && (!Is_usb_receive_nak_out())); - - //Check for NAK - if (Is_usb_receive_nak_out()) { - Usb_ack_nak_out(); - break; - } - - bytecounter = Usb_byte_counter_8(); - - //ZLP? - if (bytecounter == 0) - break; - } - - } - - //Read the data itself in - uint8_t * uipdata = uip_buf; - uint16_t datalen = PBUF->DataLength; - - while(datalen) { - *uipdata++ = Usb_read_byte(); - datalen--; - bytecounter--; - - //If endpoint is done - if (bytecounter == 0) { - //Might be everything we need! - if (datalen) { - Usb_ack_receive_out(); - //Wait for new data - while (!Is_usb_receive_out()); - bytecounter = Usb_byte_counter_8(); - } - } - - } - - //Ack final data packet - Usb_ack_receive_out(); - - //Send data over RF or to local stack - uip_len = PBUF->DataLength; //uip_len includes LLH_LEN - mac_ethernetToLowpan(uip_buf); - - - - } //if (PBUF->DataLength) - - - } //if(Is_usb_receive_out() && (uip_len == 0)) - - } // if (rndis_data_intialized) - else if(Is_device_enumerated() && //Enumeration processs OK && - (usb_mode == eem) ) //USB Stick is using EEM - { - uint16_t datalength; - - if (doInit) { - mac_ethernetSetup(); - doInit = 0; - } - - //Connected! - Led0_on(); - - Usb_select_endpoint(RX_EP); - - //If we have data and a free buffer - if(Is_usb_receive_out() && (uip_len == 0)) { - - //Read how much (endpoint only stores up to 64 bytes anyway) - bytecounter = Usb_byte_counter_8(); - - //EEM uses 2 bytes as a header - headercounter = 2; - - uint8_t fail = 0; - - //Hmm.. what's going on here? - if (bytecounter < headercounter) { - Usb_ack_receive_out(); - //TODO CO done = 1; - } - - //Read EEM Header - i = 0; - while (headercounter) { - data_buffer[i] = Usb_read_byte(); - bytecounter--; - headercounter--; - i++; - } - - //Order is LSB/MSB, so MSN is in data_buffer[1] - //Bit 15 indicates command packet when set - if (data_buffer[1] & 0x80) { - //not a data payload - datalength = 0; - } else { - //'0' indicates data packet - //Length is lower 14 bits - datalength = data_buffer[0] | ((data_buffer[1] & 0x3F) << 8); - } - - /* EEM Command Packet */ - if ((datalength == 0) && (fail == 0)) - { - uint8_t command; - uint16_t echoLength; - - //Strip command off - command = data_buffer[1] & 0x38; - command = command >> 3; - - //Decode command type - switch (command) - { - /* Echo Request */ - case EEMCMD_ECHO: - - //Get echo length - echoLength = (data_buffer[1] & 0x07) << 8; //MSB - echoLength |= data_buffer[0]; //LSB - - //TODO: everything. oops. - - break; - - /* Everything else: Whatever. */ - case EEMCMD_ECHO_RESPONSE: - case EEMCMD_SUSPEND_HINT: - case EEMCMD_RESPONSE_HINT: - case EEMCMD_RESPONSE_COMPLETE_HINT: - case EEMCMD_TICKLE: - break; - - default: break; - } - } - /* EEM Data Packet */ - else if (datalength && (fail == 0)) - { - //Looks like we've got a live one - rx_start_led(); - - uint16_t bytes_received = 0; - uint16_t dataleft = datalength; - U8 * buffer = uip_buf; - - while(dataleft) - { - *buffer++ = Usb_read_byte(); - - dataleft--; - bytecounter--; - bytes_received++; - - //Check if endpoint is done but we are expecting more data - if ((bytecounter == 0) && (dataleft)) - { - //ACK previous data - Usb_ack_receive_out(); - - //Wait for new data - while (!Is_usb_receive_out()); - - //Get new data - bytecounter = Usb_byte_counter_8(); - - //ZLP? - if (bytecounter == 0) - { - //Incomplete!! - break; - } + + switch(usb_configuration_nb) { + case USB_CONFIG_RNDIS_DEBUG: + case USB_CONFIG_RNDIS: + if(Is_device_enumerated()) { + if(rndis_process()) { + etimer_set(&et, CLOCK_SECOND/80); + } else { + Led0_toggle(); + etimer_set(&et, CLOCK_SECOND/8); } } - - //Ack final data packet - Usb_ack_receive_out(); - - //Packet has CRC, nobody wants that garbage - datalength -= 4; - - //Send data over RF or to local stack - uip_len = datalength; //uip_len includes LLH_LEN - mac_ethernetToLowpan(uip_buf); - - } //if (datalength) - } //if(Is_usb_receive_out() && (uip_len == 0)) - } // if (Is_device_enumerated()) - - if ((usb_mode == rndis_only) || (usb_mode == rndis_debug) || (usb_mode == eem)) { - etimer_set(&et, CLOCK_SECOND/80); - } else { - etimer_set(&et, CLOCK_SECOND); + break; + case USB_CONFIG_EEM: + if(Is_device_enumerated()) + cdc_eem_process(); + etimer_set(&et, CLOCK_SECOND/80); + break; + case USB_CONFIG_ECM: + case USB_CONFIG_ECM_DEBUG: + if(Is_device_enumerated()) { + if(cdc_ecm_process()) { + etimer_set(&et, CLOCK_SECOND/80); + } else { + Led0_toggle(); + etimer_set(&et, CLOCK_SECOND/8); + } + } + break; + default: + Led0_toggle(); + etimer_set(&et, CLOCK_SECOND/4); + break; } - PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)||(usb_eth_packet_is_available()&&usb_eth_ready_for_next_packet())); } // while(1) PROCESS_END(); @@ -527,172 +298,70 @@ static uint16_t iad_fail_timeout, rndis_fail_timeout; */ uint8_t usb_eth_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) { - if (usb_mode == eem) - return eem_send(senddata, sendlen, led); + uint8_t ret = 0; + + if(!usb_eth_is_active) { + USB_ETH_HOOK_TX_ERROR("Inactive"); + goto bail; + } - if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) - return rndis_send(senddata, sendlen, led); + //Check device is set up + if (Is_device_enumerated() == 0) { + USB_ETH_HOOK_TX_ERROR("Device not enumerated"); + goto bail; + } + switch(usb_configuration_nb) { + case USB_CONFIG_RNDIS_DEBUG: + case USB_CONFIG_RNDIS: + ret = rndis_send(senddata, sendlen, led); + break; + case USB_CONFIG_EEM: + ret = eem_send(senddata, sendlen, led); + break; + case USB_CONFIG_ECM: + case USB_CONFIG_ECM_DEBUG: + ret = ecm_send(senddata, sendlen, led); + break; + } + +bail: + + if(!ret) // Hit the watchdog if we have a successful send. + watchdog_periodic(); + + return ret; +} + +uint8_t +usb_eth_set_active(uint8_t active) { + if(usb_eth_is_active!=active) { + switch(usb_configuration_nb) { + case USB_CONFIG_RNDIS_DEBUG: + case USB_CONFIG_RNDIS: + usb_eth_is_active = active; + rndis_send_interrupt(); + break; + case USB_CONFIG_EEM: + break; + case USB_CONFIG_ECM: + case USB_CONFIG_ECM_DEBUG: + cdc_ecm_set_active(active); + usb_eth_is_active = active; + break; + } + } return 0; } -/** - \brief Send a single ethernet frame using EEM - */ -uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) -{ - //Check device is set up - if (Is_device_enumerated() == 0) - return 0; - - //Make a header - uint8_t header[2]; - - //Fake CRC! Add 4 to length for CRC - sendlen += 4; - header[0] = (sendlen >> 8) & 0x3f; - header[1] = sendlen & 0xff; - - //We send CRC seperatly.. - sendlen -= 4; - - //Send Data - Usb_select_endpoint(TX_EP); - //Usb_send_in(); - - //Wait for ready - while(!Is_usb_write_enabled()); - - //Send header (LSB then MSB) - Usb_write_byte(header[1]); - Usb_write_byte(header[0]); - - //Send packet - while(sendlen) { - Usb_write_byte(*senddata); - senddata++; - sendlen--; - - //If endpoint is full, send data in - //And then wait for data to transfer - if (!Is_usb_write_enabled()) { - Usb_send_in(); - - while(!Is_usb_write_enabled()); - } - - } - - //CRC = 0xdeadbeef - //Linux kernel 2.6.31 needs 0xdeadbeef in wrong order, - //like this: uint8_t crc[4] = {0xef, 0xbe, 0xad, 0xde}; - //This is fixed in 2.6.32 to the correct order (0xde, 0xad, 0xbe, 0xef) - uint8_t crc[4] = {0xde, 0xad, 0xbe, 0xef}; - - sendlen = 4; - uint8_t i = 0; - - //Send fake CRC - while(sendlen) { - Usb_write_byte(crc[i]); - i++; - sendlen--; - - //If endpoint is full, send data in - //And then wait for data to transfer - if (!Is_usb_write_enabled()) { - Usb_send_in(); - - while(!Is_usb_write_enabled()); - } - - if (led) { - tx_end_led(); - } - } - - //Send last data in - also handles sending a ZLP if needed - Usb_send_in(); - - //Wait for ready - while(!Is_usb_write_enabled()); - - return 1; +void +usb_eth_get_mac_address(uint8_t dest[6]) { + memcpy(dest,&usb_ethernet_addr,6); } -/** - \brief Send data over RNDIS interface, data is in uipbuf and length is uiplen - */ -uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) -{ - - - uint16_t i; - - //Setup Header - PBUF->MessageType = REMOTE_NDIS_PACKET_MSG; - PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t); - PBUF->DataLength = sendlen; - PBUF->OOBDataLength = 0; - PBUF->OOBDataOffset = 0; - PBUF->NumOOBDataElements = 0; - PBUF->PerPacketInfoOffset = 0; - PBUF->PerPacketInfoLength = 0; - PBUF->DeviceVcHandle = 0; - PBUF->Reserved = 0; - PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength; - - //Send Data - Usb_select_endpoint(TX_EP); - Usb_send_in(); - - //Wait for ready - while(!Is_usb_write_enabled()); - - //Setup first part of transfer... - for(i = 0; i < sizeof(rndis_data_packet_t); i++) { - Usb_write_byte(data_buffer[i]); - } - - //Send packet - while(sendlen) { - Usb_write_byte(*senddata); - senddata++; - sendlen--; - - //If endpoint is full, send data in - //And then wait for data to transfer - if (!Is_usb_write_enabled()) { - Usb_send_in(); - - while(!Is_usb_write_enabled()); - } - - if (led) { - tx_end_led(); - } - } - - Usb_send_in(); - - return 1; +void +usb_eth_set_mac_address(const uint8_t src[6]) { + memcpy(&usb_ethernet_addr,src,6); } -/** - @brief This will enable the RX_START LED for a period -*/ -void rx_start_led(void) -{ - Led1_on(); - led1_timer = 10; -} - -/** - @brief This will enable the TRX_END LED for a period -*/ -void tx_end_led(void) -{ - Led2_on(); - led2_timer = 10; -} /** @} */ diff --git a/cpu/avr/dev/usb/rndis/rndis_task.h b/cpu/avr/dev/usb/rndis/rndis_task.h index 6bbdc90c1..a39b3651a 100644 --- a/cpu/avr/dev/usb/rndis/rndis_task.h +++ b/cpu/avr/dev/usb/rndis/rndis_task.h @@ -52,22 +52,72 @@ #include "config.h" +#include "../conf_usb.h" //_____ M A C R O S ________________________________________________________ +#define USB_ETH_MTU UIP_BUFSIZE+4 +/*! Hook Documentation +** USB_ETH_HOOK_RX_START() +** USB_ETH_HOOK_RX_END() +** USB_ETH_HOOK_RX_ERROR(string_reason) +** +** USB_ETH_HOOK_TX_START() +** USB_ETH_HOOK_TX_END() +** USB_ETH_HOOK_TX_ERROR(string_reason) +** +** USB_ETH_HOOK_INITIALIZED() +** USB_ETH_HOOK_UNINITIALIZED() +** +** USB_ETH_HOOK_INIT() +** +** USB_ETH_HOOK_SET_PROMISCIOUS_MODE(bool) +** +** USB_ETH_HOOK_HANDLE_INBOUND_PACKET(buffer,len) +** USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET() +*/ + + + +#ifndef USB_ETH_HOOK_RX_START +void rx_start_led(void); +#define USB_ETH_HOOK_RX_START() rx_start_led() +#endif + +#ifndef USB_ETH_HOOK_TX_END +void tx_end_led(void); +#define USB_ETH_HOOK_TX_END() tx_end_led() +#endif + + + +#ifndef USB_ETH_HOOK_TX_ERROR +#define USB_ETH_HOOK_TX_ERROR(string) do { } while(0) +#endif + +#ifndef USB_ETH_HOOK_RX_ERROR +#define USB_ETH_HOOK_RX_ERROR(string) do { } while(0) +#endif + //_____ D E C L A R A T I O N S ____________________________________________ + uint8_t usb_eth_send(uint8_t * senddata, uint16_t sendlen, uint8_t led); +uint8_t usb_eth_set_active(uint8_t active); +uint8_t usb_eth_ready_for_next_packet(); void sof_action(void); -void rx_start_led(void); -void tx_end_led(void); -extern char usb_busy; +extern uint8_t usb_eth_is_active; -PROCESS_NAME(rndis_process); +// TIP: Avoid using usb_ethernet_addr directly and use the get/set mac_address functions below. +extern uint64_t usb_ethernet_addr; +void usb_eth_get_mac_address(uint8_t dest[6]); +void usb_eth_set_mac_address(const uint8_t src[6]); + +PROCESS_NAME(usb_eth_process); /** @} */ diff --git a/cpu/avr/dev/usb/serial/cdc_task.c b/cpu/avr/dev/usb/serial/cdc_task.c index d4cdecc49..e69de29bb 100644 --- a/cpu/avr/dev/usb/serial/cdc_task.c +++ b/cpu/avr/dev/usb/serial/cdc_task.c @@ -1,383 +0,0 @@ -/* This file has been prepared for Doxygen automatic documentation generation.*/ -/*! \file cdc_task.c ********************************************************** - * - * \brief - * Manages the CDC-ACM Virtual Serial Port Dataclass for the USB Device - * - * \addtogroup usbstick - * - * \author - * Colin O'Flynn - * - ******************************************************************************/ -/* Copyright (c) 2008 ATMEL Corporation - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ -/** - \ingroup usbstick - \defgroup cdctask CDC Task - @{ - */ - -//_____ I N C L U D E S ___________________________________________________ - - -#include "contiki.h" -#include "usb_drv.h" -#include "usb_descriptors.h" -#include "usb_specific_request.h" -#include "serial/cdc_task.h" -#include "serial/uart_usb_lib.h" -#include "rndis/rndis_protocol.h" -#include "sicslow_ethernet.h" -#if RF230BB -extern void rf230_set_channel(int channel); -extern int rf230_get_channel(void); -#else -#include "radio.h" -#endif -#include -#include - -#include -#include -#include - -#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) -#define PRINTF printf -#define PRINTF_P printf_P - -//_____ M A C R O S ________________________________________________________ - - - - - -//_____ D E F I N I T I O N S ______________________________________________ - - -#define IAD_TIMEOUT_DETACH 300 -#define IAD_TIMEOUT_ATTACH 600 -#define PBUF ((rndis_data_packet_t *) data_buffer) - -//_____ D E C L A R A T I O N S ____________________________________________ - - -void menu_print(void); -void menu_process(char c); - -extern char usb_busy; - -//! Counter for USB Serial port -extern U8 tx_counter; - -//! Timers for LEDs -uint8_t led3_timer; - - -//! Was USB device *just* enumerated? -uint8_t justenumerated = 1; - - -static uint8_t timer = 0; -static struct etimer et; - - -PROCESS(cdc_process, "CDC process"); - -/** - * \brief Communication Data Class (CDC) Process - * - * This is the link between USB and the "good stuff". In this routine data - * is received and processed by CDC-ACM Class - */ -PROCESS_THREAD(cdc_process, ev, data_proc) -{ - - PROCESS_BEGIN(); - uart_usb_init(); - - while(1) { - - - // turn off LED's if necessary - if (led3_timer) led3_timer--; - else Led3_off(); - - if(Is_device_enumerated() && (usb_mode == rndis_debug) && rndis_state && (!usb_busy)) { - - if (justenumerated) { - - //If we have serial port, set it as output - if (usb_mode == rndis_debug) { - uart_usb_set_stdout(); - menu_print(); - } - justenumerated = 0; - } - - //Flush buffer if timeout - if(timer >= 4 && tx_counter!=0 ){ - timer = 0; - uart_usb_flush(); - } else { - timer++; - } - - while (uart_usb_test_hit()){ - menu_process(uart_usb_getchar()); // See what they want - } - - - }//if (Is_device_enumerated()) - - - if (usb_mode == rndis_debug) { - etimer_set(&et, CLOCK_SECOND/80); - } else { - etimer_set(&et, CLOCK_SECOND); - } - - PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); - - } // while(1) - - PROCESS_END(); -} - -/** - \brief Print debug menu - */ -void menu_print(void) -{ - PRINTF_P(PSTR("\n\n\r********** Jackdaw Menu ******************\n\r")); - PRINTF_P(PSTR("* *\n\r")); - PRINTF_P(PSTR("* Main Menu: *\n\r")); - PRINTF_P(PSTR("* h,? Print this menu *\n\r")); - PRINTF_P(PSTR("* m Print current mode *\n\r")); - PRINTF_P(PSTR("* s Set to sniffer mode *\n\r")); - PRINTF_P(PSTR("* n Set to network mode *\n\r")); - PRINTF_P(PSTR("* c Set RF channel *\n\r")); - PRINTF_P(PSTR("* 6 Toggle 6lowpan *\n\r")); - PRINTF_P(PSTR("* r Toggle raw mode *\n\r")); - PRINTF_P(PSTR("* u Switch to mass-storage*\n\r")); - PRINTF_P(PSTR("* *\n\r")); - PRINTF_P(PSTR("* Make selection at any time by pressing *\n\r")); - PRINTF_P(PSTR("* your choice on keyboard. *\n\r")); - PRINTF_P(PSTR("******************************************\n\r")); -} - -/** - \brief Process incomming char on debug port - */ -void menu_process(char c) -{ - - static enum menustate_enum /* Defines an enumeration type */ - { - normal, - channel - } menustate = normal; - - static char channel_string[3]; - static uint8_t channel_string_i = 0; - - int tempchannel; - - - if (menustate == channel) { - - switch(c) { - case '\r': - case '\n': - channel_string[channel_string_i] = 0; - - //Will return zero in event of error... - tempchannel = atoi(channel_string); - - //Bounds check only if user had real input - if ( ((channel_string_i) && (tempchannel < 11)) || (tempchannel > 26)) { - PRINTF_P(PSTR("\n\rInvalid input\n\r")); - } - - //If valid input, change it - if (tempchannel) { -#if RF230BB - rf230_set_channel(tempchannel); -#else - radio_set_operating_channel(tempchannel); -#endif -// eeprom_write_byte((uint8_t *) 9, tempchannel); //Write channel -// eeprom_write_byte((uint8_t *)10, ~tempchannel); //Bit inverse as check - } - - menustate = normal; - break; - - case '\b': - - if (channel_string_i) - channel_string_i--; - break; - - default: - - if (channel_string_i > 1) { - menustate = normal; - PRINTF_P(PSTR("\n\rInput too long!\n\r")); - break; - } - - channel_string[channel_string_i] = c; - channel_string_i++; - } - - - } else { - - uint8_t i; - switch(c) { - case '\r': - case '\n': - break; - - case 'h': - case '?': - menu_print(); - break; - - case 's': - PRINTF_P(PSTR("Jackdaw now in sniffer mode\n\r")); - usbstick_mode.sendToRf = 0; - usbstick_mode.translate = 0; - break; - - case 'n': - PRINTF_P(PSTR("Jackdaw now in network mode\n\r")); - usbstick_mode.sendToRf = 1; - usbstick_mode.translate = 1; - break; - - case '6': - if (usbstick_mode.sicslowpan) { - PRINTF_P(PSTR("Jackdaw does not perform 6lowpan translation\n\r")); - usbstick_mode.sicslowpan = 0; - } else { - PRINTF_P(PSTR("Jackdaw now performs 6lowpan translations\n\r")); - usbstick_mode.sicslowpan = 1; - } - - break; - - case 'r': - if (usbstick_mode.raw) { - PRINTF_P(PSTR("Jackdaw does not capture raw frames\n\r")); - usbstick_mode.raw = 0; - } else { - PRINTF_P(PSTR("Jackdaw now captures raw frames\n\r")); - usbstick_mode.raw = 1; - } - break; - - case 'c': -#if RF230BB - PRINTF_P(PSTR("Select 802.15.4 Channel in range 11-26 [%d]: "), rf230_get_channel()); -#else - PRINTF_P(PSTR("Select 802.15.4 Channel in range 11-26 [%d]: "), radio_get_operating_channel()); -#endif - menustate = channel; - channel_string_i = 0; - break; - - - - case 'm': - PRINTF_P(PSTR("Currently Jackdaw:\n\r * Will ")); - if (usbstick_mode.sendToRf == 0) { PRINTF_P(PSTR("not "));} - PRINTF_P(PSTR("send data over RF\n\r * Will ")); - if (usbstick_mode.translate == 0) { PRINTF_P(PSTR("not "));} - PRINTF_P(PSTR("change link-local addresses inside IP messages\n\r * Will ")); - if (usbstick_mode.sicslowpan == 0) { PRINTF_P(PSTR("not "));} - PRINTF_P(PSTR("decompress 6lowpan headers\n\r * Will ")); - if (usbstick_mode.raw == 0) { PRINTF_P(PSTR("not "));} - PRINTF_P(PSTR("Output raw 802.15.4 frames\n\r ")); -#if RF230BB - PRINTF_P(PSTR(" * Operates on channel %d\n\r "), rf230_get_channel()); -#else - PRINTF_P(PSTR(" * Operates on channel %d\n\r "), radio_get_operating_channel()); -#endif - break; - - case 'u': - - //Mass storage mode - usb_mode = mass_storage; - - //No more serial port - stdout = NULL; - - //RNDIS is over - rndis_state = rndis_uninitialized; - Leds_off(); - - //Deatch USB - Usb_detach(); - - //Wait a few seconds - for(i = 0; i < 50; i++) - _delay_ms(100); - - //Attach USB - Usb_attach(); - - - break; - - default: - PRINTF_P(PSTR("%c is not a valid option! h for menu\n\r"), c); - break; - } - - - } - - return; - -} - - -/** - @brief This will enable the VCP_TRX_END LED for a period -*/ -void vcptx_end_led(void) -{ - Led3_on(); - led3_timer = 10; -} -/** @} */ - diff --git a/cpu/avr/dev/usb/serial/cdc_task.h b/cpu/avr/dev/usb/serial/cdc_task.h index 66042b49d..e69de29bb 100644 --- a/cpu/avr/dev/usb/serial/cdc_task.h +++ b/cpu/avr/dev/usb/serial/cdc_task.h @@ -1,74 +0,0 @@ -/* This file has been prepared for Doxygen automatic documentation generation.*/ -/*! \file cdc_task.h ************************************************************ - * - * \brief - * This file manages the CDC task for the virtual COM port. - * - * \addtogroup usbstick - * - * \author - * Colin O'Flynn - * - ******************************************************************************/ -/* Copyright (c) 2008 ATMEL Corporation - Copyright (c) 2008 Colin O'Flynn - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _CDC_TASK_H_ -#define _CDC_TASK_H_ - -/** - \addtogroup cdctask - @{ - */ - -//_____ I N C L U D E S ____________________________________________________ - - -#include "config.h" - -//_____ M A C R O S ________________________________________________________ - - - -//_____ D E C L A R A T I O N S ____________________________________________ - - -void sof_action(void); -void vcptx_end_led(void); - -void rawmode_enable(void); -void rawmode_disable(void); - -PROCESS_NAME(cdc_process); - -/** @} */ - -#endif /* _CDC_TASK_H_ */ - diff --git a/cpu/avr/dev/usb/serial/uart_usb_lib.c b/cpu/avr/dev/usb/serial/uart_usb_lib.c index 49a3d9d3f..3b160f3f1 100644 --- a/cpu/avr/dev/usb/serial/uart_usb_lib.c +++ b/cpu/avr/dev/usb/serial/uart_usb_lib.c @@ -45,7 +45,6 @@ #include "config.h" #include "usb_drv.h" #include "usb_descriptors.h" -#include "serial/cdc_task.h" #include "serial/uart_usb_lib.h" #include @@ -56,6 +55,26 @@ /*_____ M A C R O S ________________________________________________________*/ +#ifndef USB_CDC_ACM_HOOK_TX_START +#define USB_CDC_ACM_HOOK_TX_START(char) +#endif + +#ifndef USB_CDC_ACM_HOOK_TX_END +#define USB_CDC_ACM_HOOK_TX_END(char) +#endif + +#ifndef USB_CDC_ACM_HOOK_CLS_CHANGED +#define USB_CDC_ACM_HOOK_CLS_CHANGED(state) +#endif + +#ifndef USB_CDC_ACM_HOOK_CONFIGURED +#define USB_CDC_ACM_HOOK_CONFIGURED() +#endif + +#ifndef USB_CDC_ACM_CONF_LOCAL_ECHO +#define USB_CDC_ACM_CONF_LOCAL_ECHO 0 +#endif + /*_____ D E F I N I T I O N ________________________________________________*/ Uchar tx_counter; @@ -64,22 +83,65 @@ S_line_coding line_coding; /*_____ D E C L A R A T I O N ______________________________________________*/ +void uart_usb_configure_endpoints() { + usb_configure_endpoint( + VCP_INT_EP, + TYPE_INTERRUPT, + DIRECTION_IN, + SIZE_32, + ONE_BANK, + NYET_ENABLED + ); + + usb_configure_endpoint( + VCP_TX_EP, + TYPE_BULK, + DIRECTION_IN, + SIZE_32, + TWO_BANKS, + NYET_ENABLED + ); + + usb_configure_endpoint( + VCP_RX_EP, + TYPE_BULK, + DIRECTION_OUT, + SIZE_32, + TWO_BANKS, + NYET_ENABLED + ); + + Usb_reset_endpoint(VCP_INT_EP); + Usb_reset_endpoint(VCP_TX_EP); + Usb_reset_endpoint(VCP_RX_EP); + + USB_CDC_ACM_HOOK_CONFIGURED(); +} + int usb_stdout_putchar(char c, FILE *stream) - { - // send to USB port - // don't send anything if USB can't accept chars - Usb_select_endpoint(TX_EP); - if (!uart_usb_tx_ready()) - return 0; - - // turn on LED - vcptx_end_led(); +{ + // Preserve the currently selected endpoint + uint8_t uenum = UENUM; + + // send to USB port + // don't send anything if USB can't accept chars + Usb_select_endpoint(VCP_TX_EP); + + if(usb_endpoint_wait_for_write_enabled()!=0) + return 0; + + if(c=='\n') + uart_usb_putchar('\r'); + + if(c!='\r') + uart_usb_putchar(c); + + // Restore previously selected endpoint + UENUM = uenum; - uart_usb_putchar(c); - return 0; - } +} static FILE usb_stdout = FDEV_SETUP_STREAM(usb_stdout_putchar, NULL, @@ -100,6 +162,20 @@ void uart_usb_set_stdout(void) } +static uint8_t uart_usb_control_line_state = 0; + +uint8_t uart_usb_get_control_line_state(void) { + return uart_usb_control_line_state; +} + + +void uart_usb_set_control_line_state(uint8_t control_line_state) +{ + uart_usb_control_line_state = control_line_state; + USB_CDC_ACM_HOOK_CLS_CHANGED(control_line_state); +} + + /** * @brief This function checks if the USB emission buffer is ready to accept at * at least 1 byte @@ -109,6 +185,7 @@ void uart_usb_set_stdout(void) */ bit uart_usb_tx_ready(void) { + Usb_select_endpoint(VCP_TX_EP); if (!Is_usb_write_enabled()) { return FALSE; @@ -127,16 +204,31 @@ bit uart_usb_tx_ready(void) */ int uart_usb_putchar(int data_to_send) { - Usb_select_endpoint(VCP_TX_EP); - - if(!uart_usb_tx_ready()) return -1; - + // Preserve the currently selected endpoint + uint8_t uenum = UENUM; + + USB_CDC_ACM_HOOK_TX_START(data_to_send); + + Usb_select_endpoint(VCP_TX_EP); + + if(!uart_usb_tx_ready()) { + data_to_send=-1; + goto bail; + } + Usb_write_byte(data_to_send); tx_counter++; - if(!Is_usb_write_enabled()) //If Endpoint full -> flush - { - uart_usb_flush(); - } + + //If Endpoint full -> flush + if(!Is_usb_write_enabled()) + uart_usb_flush(); + + USB_CDC_ACM_HOOK_TX_END(data_to_send); + +bail: + // Restore previously selected endpoint + UENUM = uenum; + return data_to_send; } @@ -149,6 +241,8 @@ bit uart_usb_test_hit(void) { if (!rx_counter) { + // Preserve the currently selected endpoint + uint8_t uenum = UENUM; Usb_select_endpoint(VCP_RX_EP); if (Is_usb_receive_out()) { @@ -158,6 +252,8 @@ bit uart_usb_test_hit(void) Usb_ack_receive_out(); } } + // Restore previously selected endpoint + UENUM = uenum; } return (rx_counter!=0); } @@ -174,15 +270,23 @@ char uart_usb_getchar(void) { register Uchar data_rx; + // Preserve the currently selected endpoint + uint8_t uenum = UENUM; + Usb_select_endpoint(VCP_RX_EP); if (!rx_counter) while (!uart_usb_test_hit()); data_rx=Usb_read_byte(); rx_counter--; if (!rx_counter) Usb_ack_receive_out(); +#if USB_CDC_ACM_CONF_LOCAL_ECHO //Local echo uart_usb_putchar(data_rx); +#endif + // Restore previously selected endpoint + UENUM = uenum; + return data_rx; } @@ -193,9 +297,16 @@ char uart_usb_getchar(void) */ void uart_usb_flush (void) { - Usb_select_endpoint(VCP_TX_EP); - Usb_send_in(); + // Preserve the currently selected endpoint + uint8_t uenum = UENUM; + + Usb_select_endpoint(VCP_TX_EP); + Usb_send_in(); tx_counter = 0; + usb_endpoint_wait_for_write_enabled(); + + // Restore previously selected endpoint + UENUM = uenum; } /** @} */ diff --git a/cpu/avr/dev/usb/serial/uart_usb_lib.h b/cpu/avr/dev/usb/serial/uart_usb_lib.h index 233c800f3..9d12e604c 100644 --- a/cpu/avr/dev/usb/serial/uart_usb_lib.h +++ b/cpu/avr/dev/usb/serial/uart_usb_lib.h @@ -78,6 +78,10 @@ void uart_usb_flush(void); bit uart_usb_test_hit(void); char uart_usb_getchar(void); void uart_usb_set_stdout(void); +uint8_t uart_usb_get_control_line_state(void); +void uart_usb_set_control_line_state(uint8_t control_line_state); + +extern void uart_usb_configure_endpoints(); /** @} **/ diff --git a/cpu/avr/dev/usb/usb_descriptors.c b/cpu/avr/dev/usb/usb_descriptors.c index d2a172894..9c140e75f 100644 --- a/cpu/avr/dev/usb/usb_descriptors.c +++ b/cpu/avr/dev/usb/usb_descriptors.c @@ -55,17 +55,252 @@ #include "usb_drv.h" #include "usb_descriptors.h" #include "usb_specific_request.h" +#include "rndis/rndis_task.h" //_____ M A C R O S ________________________________________________________ +#define USB_ETH_NET_FUNC_DESC(MACAddrString,etherStat,maxSegmentSize,nMCFilters,nPowerFilters) \ + { sizeof(S_usb_ethernet_networking_functional_descriptor) \ + , 0x24, 0x0F \ +, MACAddrString \ +, etherStat \ +, Usb_write_word_enum_struc(maxSegmentSize) \ +, Usb_write_word_enum_struc(nMCFilters) \ +, nPowerFilters \ +} + + + +#define USB_CONFIG_DESC(totalsize,interfaceCount,value,stringIndex,attr,power) \ + { sizeof(S_usb_configuration_descriptor) \ + , CONFIGURATION_DESCRIPTOR \ + , Usb_write_word_enum_struc(totalsize) \ + , interfaceCount \ + , value \ + , stringIndex \ + , attr \ + , power \ + } + +#define USB_ENDPOINT(nb,attr,maxpktsize,interval) \ +{ sizeof(S_usb_endpoint_descriptor) \ + , ENDPOINT_DESCRIPTOR \ + , nb \ + , attr \ + , Usb_write_word_enum_struc(maxpktsize) \ + , interval \ + } + +#define USB_IAD(firstinterface,interfacecount,funcClass,funcSubClass,funcProto,stringIndex) \ + { \ + sizeof(S_usb_interface_association_descriptor), \ + DSC_TYPE_IAD, \ + firstinterface, \ + interfacecount, \ + funcClass, \ + funcSubClass, \ + funcProto, \ + stringIndex \ + } + +#define USB_INTERFACEDESC(nb,altsetting,endpointCount,interfaceClass,interfaceSubClass,interfaceProto,stringIndex) \ + { sizeof(S_usb_interface_descriptor) \ + , INTERFACE_DESCRIPTOR \ + , nb \ + , altsetting \ + , endpointCount \ + , interfaceClass \ + , interfaceSubClass \ + , interfaceProto \ + , stringIndex \ + } + + +#define FUNC_DESC_HEADER \ +0x05, /* bFunctionLength, Descriptor size in bytes*/ \ +0x24, /* bDescriptorType, CS_INTERFACE */ \ +0x00, /* bDescriptorSubtype, Header Functional Descriptor */ \ +0x10,0x01 /* bcdCDC, CDC specification release number in BCD format (1,1) */ + +#define FUNC_DESC_CALL_MANAGEMENT(caps,dataInterface) \ +0x05, /* bFunctionLength, Descriptor size in bytes */ \ +0x24, /* bDescriptorType, CS_INTERFACE */ \ +0x01, /* bDescriptorSubtype, Call Management Functional Descriptor */ \ +caps, /* bmCapabilities */ \ +dataInterface /* bDataInterface, Interface used for call management */ + +/* Abstract Control Management Functional Descriptor */ +#define FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(caps) \ +0x04, /* bFunctionLength, Descriptor size in bytes */ \ +0x24, /* bDescriptorType, CS_INTERFACE */ \ +0x02, /* bDescriptorSubtype, Call Management Functional Descriptor */ \ +caps /* bmCapabilities */ + +/* Union Functional Descriptor */ \ +#define FUNC_DESC_UNION(masterInterface,slaveInterface) \ +0x05, /* bFunctionLength, Descriptor size in bytes */ \ +0x24, /* bDescriptorType, CS_INTERFACE */ \ +0x06, /* bDescriptorSubtype, Union Functional Descriptor */ \ +masterInterface, /* bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) */ \ +slaveInterface /* bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) */ \ + + +#define RNDIS_INTERFACES \ +USB_INTERFACEDESC( \ + INTERFACE0_NB, \ + ALTERNATE0, \ + NB_ENDPOINT0, \ + INTERFACE0_CLASS, \ + INTERFACE0_SUB_CLASS, \ + INTERFACE0_PROTOCOL, \ + USB_STRING_INTERFACE_RNDIS \ +), \ + { \ + FUNC_DESC_HEADER, \ + FUNC_DESC_CALL_MANAGEMENT(0x00/*caps*/,0x00/*dataInterface*/), \ + FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(0x00), \ + FUNC_DESC_UNION(0x00,0x01), \ + }, \ + USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1), \ +\ +USB_INTERFACEDESC( \ + INTERFACE1_NB, \ + ALTERNATE1, \ + NB_ENDPOINT1, \ + INTERFACE1_CLASS, \ + INTERFACE1_SUB_CLASS, \ + INTERFACE1_PROTOCOL, \ + USB_STRING_NONE \ +), \ + USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2), \ + USB_ENDPOINT(ENDPOINT_NB_3,EP_ATTRIBUTES_3,EP_SIZE_3,EP_INTERVAL_3) + + + +#define CDC_SERIAL_INTERFACES \ +USB_INTERFACEDESC( \ + INTERFACE2_NB, \ + ALTERNATE2, \ + NB_ENDPOINT2, \ + INTERFACE2_CLASS, \ + INTERFACE2_SUB_CLASS, \ + INTERFACE2_PROTOCOL, \ + USB_STRING_INTERFACE_SERIAL \ +), \ +{ \ + FUNC_DESC_HEADER, \ + FUNC_DESC_CALL_MANAGEMENT(0x03/*caps*/,0x03/*dataInterface*/), \ + FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(0x02), \ + FUNC_DESC_UNION(0x02,0x03), \ +}, \ +USB_ENDPOINT(ENDPOINT_NB_4,EP_ATTRIBUTES_4,EP_SIZE_4,EP_INTERVAL_4), \ +USB_INTERFACEDESC( \ + INTERFACE3_NB, \ + ALTERNATE3, \ + NB_ENDPOINT3, \ + INTERFACE3_CLASS, \ + INTERFACE3_SUB_CLASS, \ + INTERFACE3_PROTOCOL, \ + USB_STRING_NONE \ +), \ +USB_ENDPOINT(ENDPOINT_NB_5,EP_ATTRIBUTES_5,EP_SIZE_5,EP_INTERVAL_5), \ +USB_ENDPOINT(ENDPOINT_NB_6,EP_ATTRIBUTES_6,EP_SIZE_6,EP_INTERVAL_6) + + + + + +#define CDC_EEM_INTERFACES \ +USB_INTERFACEDESC( \ + EEM_INTERFACE0_NB, \ + EEM_ALTERNATE0, \ + EEM_NB_ENDPOINT0, \ + EEM_INTERFACE0_CLASS, \ + EEM_INTERFACE0_SUB_CLASS, \ + EEM_INTERFACE0_PROTOCOL, \ + USB_STRING_INTERFACE_EEM \ +), \ + USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1), \ + USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2) + + + + +#if CDC_ECM_USES_INTERRUPT_ENDPOINT +#define CDC_ECM_CONTROL_ENDPOINT_COUNT 1 +#define CDC_ECM_CONTROL_ENDPOINT USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1), +#else +#define CDC_ECM_CONTROL_ENDPOINT_COUNT 0 +#define CDC_ECM_CONTROL_ENDPOINT +#endif + + +#define CDC_ECM_INTERFACES \ +USB_INTERFACEDESC( \ + ECM_INTERFACE0_NB, \ + ECM_ALTERNATE0, \ + CDC_ECM_CONTROL_ENDPOINT_COUNT, \ + ECM_INTERFACE0_CLASS, \ + ECM_INTERFACE0_SUB_CLASS, \ + ECM_INTERFACE0_PROTOCOL, \ + USB_STRING_INTERFACE_ECM \ +), \ +{ \ + FUNC_DESC_HEADER, \ + FUNC_DESC_UNION(0x00,0x01), \ +}, \ + USB_ETH_NET_FUNC_DESC( \ + USB_STRING_MAC_ADDRESS, \ + 0, /* Support no stats for now */ \ + USB_ETH_MTU, /* maxSegmentSize */ \ + 0, /* nMCFilters*/ \ + 0 /*nPowerFilters*/ \ + ), \ + CDC_ECM_CONTROL_ENDPOINT \ +USB_INTERFACEDESC( \ + ECM_INTERFACE0_NB+1, \ + 0, \ + 2, \ + 10, \ + 0, \ + 0, \ + USB_STRING_NONE \ +), \ + USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2), \ + USB_ENDPOINT(ENDPOINT_NB_3,EP_ATTRIBUTES_3,EP_SIZE_3,EP_INTERVAL_3) + +/* +USB_INTERFACEDESC( \ + ECM_INTERFACE0_NB+1, \ + 0, \ + 0, \ + 10, \ + 0, \ + 0, \ + USB_STRING_NONE \ +), \ +*/ + //_____ D E F I N I T I O N ________________________________________________ /************* COMPOSITE DEVICE DESCRIPTORS (using IAD) **********/ +FLASH uint8_t usb_dev_config_order[] = { +// USB_CONFIG_RNDIS_DEBUG, //Enable here for Windows COM port debugging? (USB_CONF_CDC=1) + USB_CONFIG_RNDIS, + USB_CONFIG_ECM_DEBUG, + USB_CONFIG_RNDIS_DEBUG, //Enable here for macintosh CDC-ECM enumeration + USB_CONFIG_ECM, + USB_CONFIG_EEM, +#if USB_CONF_STORAGE + USB_CONFIG_MS, +#endif +}; + // usb_user_device_descriptor FLASH S_usb_device_descriptor usb_dev_desc_composite = { @@ -79,204 +314,46 @@ FLASH S_usb_device_descriptor usb_dev_desc_composite = , Usb_write_word_enum_struc(VENDOR_ID) , Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID) , Usb_write_word_enum_struc(RELEASE_NUMBER) -, MAN_INDEX -, PROD_INDEX -, SN_INDEX -, NB_CONFIGURATION +, USB_STRING_MAN +, USB_STRING_PRODUCT +, USB_STRING_SERIAL +, (sizeof(usb_dev_config_order)/sizeof(*usb_dev_config_order)) }; // usb_user_configuration_descriptor FS FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite = { - { sizeof(S_usb_configuration_descriptor) - , CONFIGURATION_DESCRIPTOR - , Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_composite)) - //, 0x0043 //TODO: Change to generic codewith sizeof - , COMPOSITE_NB_INTERFACE - , CONF_NB - , CONF_INDEX - , CONF_ATTRIBUTES - , MAX_POWER - },//9 + USB_CONFIG_DESC( + sizeof(usb_conf_desc_composite), + COMPOSITE_NB_INTERFACE, + USB_CONFIG_RNDIS_DEBUG, + USB_STRING_CONFIG_COMPOSITE, + CONF_ATTRIBUTES, + MAX_POWER + ), - // --------------------------- IAD ---------------------------- - { // Interface Association Descriptor - sizeof(S_usb_interface_association_descriptor), // bLength - DSC_TYPE_IAD, // bDescriptorType = 11 - 0x00, // bFirstInterface - 0x02, // bInterfaceCount - 0x02, // bFunctionClass (Communication Class) - 0x02, // bFunctionSubClass (Abstract Control Model) - 0xFF, // bFunctionProcotol (Vendor specific) - 0x00 // iInterface - },//8 - - /// RNDIS DEVICE - { sizeof(S_usb_interface_descriptor) - , INTERFACE_DESCRIPTOR - , INTERFACE0_NB - , ALTERNATE0 - , NB_ENDPOINT0 - , INTERFACE0_CLASS - , INTERFACE0_SUB_CLASS - , INTERFACE0_PROTOCOL - , INTERFACE0_INDEX - } //9 -, -{ -// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors) -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x00, // bDescriptorSubtype, Header Functional Descriptor -0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1) - -// Call Management Functional Descriptor -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x01, // bDescriptorSubtype, Call Management Functional Descriptor -0x00, // bmCapabilities -0x01, // bDataInterface, Interface used for call management - -// Abstract Control Management Functional Descriptor -0x04, // bDescriptorLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor -0x00, // bmCapabilities - -// Union Functional Descriptor -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x06, // bDescriptorSubtype, Union Functional Descriptor -0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) -0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) -}, -{ sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_1 - , EP_ATTRIBUTES_1 - , Usb_write_word_enum_struc(EP_SIZE_1) - , EP_INTERVAL_1 - } //7 - , - { sizeof(S_usb_interface_descriptor) - , INTERFACE_DESCRIPTOR - , INTERFACE1_NB - , ALTERNATE1 - , NB_ENDPOINT1 - , INTERFACE1_CLASS - , INTERFACE1_SUB_CLASS - , INTERFACE1_PROTOCOL - , INTERFACE1_INDEX - }, - { sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_2 - , EP_ATTRIBUTES_2 - , Usb_write_word_enum_struc(EP_SIZE_2) - , EP_INTERVAL_2 - }, -{ sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_3 - , EP_ATTRIBUTES_3 - , Usb_write_word_enum_struc(EP_SIZE_3) - , EP_INTERVAL_3 - }, - -// --------------------------- IAD ---------------------------- - { // Interface Association Descriptor - sizeof(S_usb_interface_association_descriptor), // bLength - DSC_TYPE_IAD, // bDescriptorType = 11 - 0x02, // bFirstInterface - 0x02, // bInterfaceCount - 0x02, // bFunctionClass (Communication Class) - 0x02, // bFunctionSubClass (Abstract Control Model) - 0x01, // bFunctionProcotol (V.25ter, Common AT commands) - 0x00 // iInterface - },//8 - - /// SERIAL PORT DEVICE - - { sizeof(S_usb_interface_descriptor) - , INTERFACE_DESCRIPTOR - , INTERFACE2_NB - , ALTERNATE2 - , NB_ENDPOINT2 - , INTERFACE2_CLASS - , INTERFACE2_SUB_CLASS - , INTERFACE2_PROTOCOL - , INTERFACE2_INDEX - }//9 - , - { -// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors) -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x00, // bDescriptorSubtype, Header Functional Descriptor -0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1) - -// Call Management Functional Descriptor -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x01, // bDescriptorSubtype, Call Management Functional Descriptor -0x03, // bmCapabilities, can do calls on it's own -0x03, // bDataInterface, Interface used for call management - -// Abstract Control Management Functional Descriptor -0x04, // bDescriptorLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor -0x00, // bmCapabilities, support nothing!!! Deal with it - - //Old was 0x06 indicating support for the GET/SET_LINE_CODING, BREAK & SET_CONTROL_LINE_STATE (2->6) - -// Union Functional Descriptor -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x06, // bDescriptorSubtype, Union Functional Descriptor -0x02, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) -0x03, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) - -}, - { sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_4 - , EP_ATTRIBUTES_4 - , Usb_write_word_enum_struc(EP_SIZE_4) - , EP_INTERVAL_4 - } //7 - , - { sizeof(S_usb_interface_descriptor) - , INTERFACE_DESCRIPTOR - , INTERFACE3_NB - , ALTERNATE3 - , NB_ENDPOINT3 - , INTERFACE3_CLASS - , INTERFACE3_SUB_CLASS - , INTERFACE3_PROTOCOL - , INTERFACE3_INDEX - } - , - { sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_5 - , EP_ATTRIBUTES_5 - , Usb_write_word_enum_struc(EP_SIZE_5) - , EP_INTERVAL_5 - } - , - { sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_6 - , EP_ATTRIBUTES_6 - , Usb_write_word_enum_struc(EP_SIZE_6) - , EP_INTERVAL_6 - } + USB_IAD( + 0x00, // First interface + 0x02, // Interface count + 0x02, // Function Class + 0x02, // Function Subclass + 0xFF, // Function Protocol + USB_STRING_INTERFACE_RNDIS + ),RNDIS_INTERFACES, + USB_IAD( + 0x02, // First interface + 0x02, // Interface count + 0x02, // Function Class + 0x02, // Function Subclass + 0x01, // Function Protocol + USB_STRING_INTERFACE_SERIAL + ),CDC_SERIAL_INTERFACES }; /****************** NETWORK-ONLY DEVICE DESCRIPTORS **************************/ +/* FLASH S_usb_device_descriptor usb_dev_desc_network = { sizeof(usb_dev_desc_network) @@ -289,101 +366,115 @@ FLASH S_usb_device_descriptor usb_dev_desc_network = , Usb_write_word_enum_struc(VENDOR_ID) , Usb_write_word_enum_struc(NETWORK_PRODUCT_ID) , Usb_write_word_enum_struc(RELEASE_NUMBER) -, MAN_INDEX -, PROD_INDEX -, SN_INDEX +, USB_STRING_MAN +, USB_STRING_PRODUCT +, USB_STRING_SERIAL , NB_CONFIGURATION }; +*/ // usb_user_configuration_descriptor FS FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network = { - { sizeof(S_usb_configuration_descriptor) - , CONFIGURATION_DESCRIPTOR - , Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_network)) - //, 0x0043 //TODO: Change to generic codewith sizeof - , NETWORK_NB_INTERFACE - , CONF_NB - , CONF_INDEX - , CONF_ATTRIBUTES - , MAX_POWER - },//9 - - /// RNDIS DEVICE - { sizeof(S_usb_interface_descriptor) - , INTERFACE_DESCRIPTOR - , INTERFACE0_NB - , ALTERNATE0 - , NB_ENDPOINT0 - , INTERFACE0_CLASS - , INTERFACE0_SUB_CLASS - , INTERFACE0_PROTOCOL - , INTERFACE0_INDEX - } //9 -, -{ -// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors) -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x00, // bDescriptorSubtype, Header Functional Descriptor -0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1) - -// Call Management Functional Descriptor -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x01, // bDescriptorSubtype, Call Management Functional Descriptor -0x00, // bmCapabilities -0x01, // bDataInterface, Interface used for call management - -// Abstract Control Management Functional Descriptor -0x04, // bDescriptorLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor -0x00, // bmCapabilities - -// Union Functional Descriptor -0x05, // bFunctionLength, Descriptor size in bytes -0x24, // bDescriptorType, CS_INTERFACE -0x06, // bDescriptorSubtype, Union Functional Descriptor -0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) -0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) -}, -{ sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_1 - , EP_ATTRIBUTES_1 - , Usb_write_word_enum_struc(EP_SIZE_1) - , EP_INTERVAL_1 - } //7 - , - { sizeof(S_usb_interface_descriptor) - , INTERFACE_DESCRIPTOR - , INTERFACE1_NB - , ALTERNATE1 - , NB_ENDPOINT1 - , INTERFACE1_CLASS - , INTERFACE1_SUB_CLASS - , INTERFACE1_PROTOCOL - , INTERFACE1_INDEX - }, - { sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_2 - , EP_ATTRIBUTES_2 - , Usb_write_word_enum_struc(EP_SIZE_2) - , EP_INTERVAL_2 - }, -{ sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , ENDPOINT_NB_3 - , EP_ATTRIBUTES_3 - , Usb_write_word_enum_struc(EP_SIZE_3) - , EP_INTERVAL_3 - } + USB_CONFIG_DESC( + sizeof(usb_conf_desc_network), + NETWORK_NB_INTERFACE, + CONF_NB, // value + USB_STRING_CONFIG_RNDIS, + CONF_ATTRIBUTES, + MAX_POWER + ), + RNDIS_INTERFACES }; + +/************* EEM-ONLY ***************/ + +// usb_user_device_descriptor +/* +FLASH S_usb_device_descriptor usb_dev_desc_eem = +{ + sizeof(usb_dev_desc_composite) +, DEVICE_DESCRIPTOR +, Usb_write_word_enum_struc(USB_SPECIFICATION) +, EEM_DEVICE_CLASS +, EEM_DEVICE_SUB_CLASS +, EEM_DEVICE_PROTOCOL +, EP_CONTROL_LENGTH +, Usb_write_word_enum_struc(VENDOR_ID) +, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID) +, Usb_write_word_enum_struc(RELEASE_NUMBER) +, USB_STRING_MAN +, USB_STRING_PRODUCT +, USB_STRING_SERIAL +, NB_CONFIGURATION +}; +*/ + + +// usb_user_configuration_descriptor FS +FLASH S_usb_user_configuration_descriptor_eem usb_conf_desc_eem = { + USB_CONFIG_DESC( + sizeof(usb_conf_desc_eem), + EEM_NB_INTERFACE, + USB_CONFIG_EEM, // value + USB_STRING_CONFIG_EEM, + CONF_ATTRIBUTES, + MAX_POWER + ), + CDC_EEM_INTERFACES +}; + + +FLASH S_usb_user_configuration_descriptor_ecm usb_conf_desc_ecm = { + USB_CONFIG_DESC( + sizeof(usb_conf_desc_ecm), + 2, // Interface Count + USB_CONFIG_ECM, // value + USB_STRING_CONFIG_ECM, + CONF_ATTRIBUTES, + MAX_POWER + ), + CDC_ECM_INTERFACES +}; + +FLASH S_usb_user_configuration_descriptor_ecm_debug usb_conf_desc_ecm_debug = { + USB_CONFIG_DESC( + sizeof(usb_conf_desc_ecm_debug), + 4, // Interface Count + USB_CONFIG_ECM_DEBUG, // value + USB_STRING_CONFIG_ECM_DEBUG, + CONF_ATTRIBUTES, + MAX_POWER + ), + + USB_IAD( + 0x00, // First interface + 0x02, // Interface count + 0x02, // Function Class + 0x06, // Function Subclass + 0x00, // Function Protocol + USB_STRING_INTERFACE_ECM + ),CDC_ECM_INTERFACES, + + USB_IAD( + 0x02, // First interface + 0x02, // Interface count + 0x02, // Function Class + 0x02, // Function Subclass + 0x01, // Function Protocol + USB_STRING_INTERFACE_SERIAL + ),CDC_SERIAL_INTERFACES + + + +}; + + + /****************** MASS-STORAGE DEVICE DESCRIPTORS **************************/ +/* FLASH S_usb_device_descriptor usb_dev_desc_mass = { sizeof(usb_dev_desc_mass) @@ -396,11 +487,13 @@ FLASH S_usb_device_descriptor usb_dev_desc_mass = , Usb_write_word_enum_struc(VENDOR_ID) , Usb_write_word_enum_struc(MASS_PRODUCT_ID) , Usb_write_word_enum_struc(RELEASE_NUMBER) -, MAN_INDEX -, PROD_INDEX -, SN_INDEX +, USB_STRING_MAN +, USB_STRING_PRODUCT +, USB_STRING_SERIAL , NB_CONFIGURATION }; +*/ +#if USB_CONF_STORAGE // usb_user_configuration_descriptor FS FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = { @@ -409,7 +502,7 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = { , Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_mass)) , MASS_NB_INTERFACE , CONF_NB - , CONF_INDEX + , USB_STRING_CONFIG_MS , CONF_ATTRIBUTES , MAX_POWER },//9 @@ -423,7 +516,7 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = { , MS_INTERFACE_CLASS , MS_INTERFACE_SUB_CLASS , MS_INTERFACE_PROTOCOL - , MS_INTERFACE_INDEX + , USB_STRING_INTERFACE_MS } //9 , { sizeof(S_usb_endpoint_descriptor) @@ -443,96 +536,11 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = { } }; -/************* EEM-ONLY ***************/ - -// usb_user_device_descriptor -FLASH S_usb_device_descriptor usb_dev_desc_eem = -{ - sizeof(usb_dev_desc_composite) -, DEVICE_DESCRIPTOR -, Usb_write_word_enum_struc(USB_SPECIFICATION) -, EEM_DEVICE_CLASS -, EEM_DEVICE_SUB_CLASS -, EEM_DEVICE_PROTOCOL -, EP_CONTROL_LENGTH -, Usb_write_word_enum_struc(VENDOR_ID) -, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID) -, Usb_write_word_enum_struc(RELEASE_NUMBER) -, MAN_INDEX -, PROD_INDEX -, SN_INDEX -, NB_CONFIGURATION -}; - - -// usb_user_configuration_descriptor FS -FLASH S_usb_user_configuration_descriptor_eem usb_conf_desc_eem = { - { sizeof(S_usb_configuration_descriptor) - , CONFIGURATION_DESCRIPTOR - , Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_eem)) - , EEM_NB_INTERFACE - , CONF_NB - , CONF_INDEX - , CONF_ATTRIBUTES - , MAX_POWER - },//9 - /// EEM DEVICE - { sizeof(S_usb_interface_descriptor) - , INTERFACE_DESCRIPTOR - , EEM_INTERFACE0_NB - , EEM_ALTERNATE0 - , EEM_NB_ENDPOINT0 - , EEM_INTERFACE0_CLASS - , EEM_INTERFACE0_SUB_CLASS - , EEM_INTERFACE0_PROTOCOL - , EEM_INTERFACE0_INDEX - } //9 -, -{ sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , EEM_ENDPOINT_NB_1 - , EEM_EP_ATTRIBUTES_1 - , Usb_write_word_enum_struc(EEM_EP_SIZE_1) - , EEM_EP_INTERVAL_1 - } //7 - , - { sizeof(S_usb_endpoint_descriptor) - , ENDPOINT_DESCRIPTOR - , EEM_ENDPOINT_NB_2 - , EEM_EP_ATTRIBUTES_2 - , Usb_write_word_enum_struc(EEM_EP_SIZE_2) - , EEM_EP_INTERVAL_2 - } //7 -}; +#endif /************* COMMON *****************/ - // usb_user_manufacturer_string_descriptor -FLASH S_usb_manufacturer_string_descriptor usb_user_manufacturer_string_descriptor = { - sizeof(usb_user_manufacturer_string_descriptor) -, STRING_DESCRIPTOR -, USB_MANUFACTURER_NAME -}; - - - // usb_user_product_string_descriptor - -FLASH S_usb_product_string_descriptor usb_user_product_string_descriptor = { - sizeof(usb_user_product_string_descriptor) -, STRING_DESCRIPTOR -, USB_PRODUCT_NAME -}; - - - // usb_user_serial_number - -FLASH S_usb_serial_number usb_user_serial_number = { - sizeof(usb_user_serial_number) -, STRING_DESCRIPTOR -, USB_SERIAL_NUMBER -}; - // usb_user_language_id @@ -548,6 +556,8 @@ FLASH S_usb_language_id usb_user_language_id = { PGM_VOID_P Usb_get_dev_desc_pointer(void) { + return &(usb_dev_desc_composite.bLength); +/* if (usb_mode == rndis_only) return &(usb_dev_desc_network.bLength); @@ -558,11 +568,14 @@ PGM_VOID_P Usb_get_dev_desc_pointer(void) return &(usb_dev_desc_eem.bLength); return &(usb_dev_desc_mass.bLength); +*/ } U8 Usb_get_dev_desc_length(void) { + return sizeof(usb_dev_desc_composite); +/* if (usb_mode == rndis_only) return sizeof(usb_dev_desc_network); @@ -574,37 +587,54 @@ U8 Usb_get_dev_desc_length(void) return sizeof(usb_dev_desc_eem); return sizeof(usb_dev_desc_mass); +*/ } -PGM_VOID_P Usb_get_conf_desc_pointer(void) +PGM_VOID_P Usb_get_conf_desc_pointer(U8 index) { - if (usb_mode == rndis_only) - return &(usb_conf_desc_network.cfg.bLength); - - if (usb_mode == rndis_debug) - return &(usb_conf_desc_composite.cfg.bLength); - - if (usb_mode == eem) - return &(usb_conf_desc_eem.cfg.bLength); - - return &(usb_conf_desc_mass.cfg.bLength); + + switch(pgm_read_byte_near(&usb_dev_config_order[index])) { + case USB_CONFIG_ECM: + return &(usb_conf_desc_ecm.cfg.bLength); + case USB_CONFIG_ECM_DEBUG: + return &(usb_conf_desc_ecm_debug.cfg.bLength); + case USB_CONFIG_RNDIS_DEBUG: + return &(usb_conf_desc_composite.cfg.bLength); + case USB_CONFIG_RNDIS: + return &(usb_conf_desc_network.cfg.bLength); + case USB_CONFIG_EEM: + return &(usb_conf_desc_eem.cfg.bLength); +#if USB_CONF_STORAGE + case USB_CONFIG_MS: + return &(usb_conf_desc_mass.cfg.bLength); +#endif + default: + return 0; + } } -U8 Usb_get_conf_desc_length(void) +U8 Usb_get_conf_desc_length(U8 index) { - - if (usb_mode == rndis_only) - return sizeof (usb_conf_desc_network); - - if (usb_mode == rndis_debug) - return sizeof(usb_conf_desc_composite); - - if (usb_mode == eem) - return sizeof(usb_conf_desc_eem); - - return sizeof(usb_conf_desc_mass); + switch(pgm_read_byte_near(&usb_dev_config_order[index])) { + case USB_CONFIG_ECM: + return sizeof(usb_conf_desc_ecm); + case USB_CONFIG_ECM_DEBUG: + return sizeof(usb_conf_desc_ecm_debug); + case USB_CONFIG_RNDIS_DEBUG: + return sizeof(usb_conf_desc_composite); + case USB_CONFIG_RNDIS: + return sizeof (usb_conf_desc_network); + case USB_CONFIG_EEM: + return sizeof(usb_conf_desc_eem); +#if USB_CONF_STORAGE + case USB_CONFIG_MS: + return sizeof(usb_conf_desc_mass); +#endif + default: + return 0; + } } /** @} */ diff --git a/cpu/avr/dev/usb/usb_descriptors.h b/cpu/avr/dev/usb/usb_descriptors.h index 808dcadb0..667c5c369 100644 --- a/cpu/avr/dev/usb/usb_descriptors.h +++ b/cpu/avr/dev/usb/usb_descriptors.h @@ -66,9 +66,9 @@ // USB Device descriptor #define USB_SPECIFICATION 0x0200 -#define COMPOSITE_DEVICE_CLASS 0xEF // Misc -#define COMPOSITE_DEVICE_SUB_CLASS 0x02 // Common -#define COMPOSITE_DEVICE_PROTOCOL 0x01 // IAD +#define COMPOSITE_DEVICE_CLASS 0x02 // Misc +#define COMPOSITE_DEVICE_SUB_CLASS 0x00 // Common +#define COMPOSITE_DEVICE_PROTOCOL 0x00 // IAD #define NETWORK_DEVICE_CLASS 0x02 // CDC ACM #define NETWORK_DEVICE_SUB_CLASS 0x02 // @@ -88,10 +88,49 @@ #define NETWORK_PRODUCT_ID 0x2019 //Product ID for just RNDIS device #define MASS_PRODUCT_ID 0x202F //Product ID for mass storage #define RELEASE_NUMBER 0x1000 -#define MAN_INDEX 0x01 -#define PROD_INDEX 0x02 -#define SN_INDEX 0x03 -#define NB_CONFIGURATION 1 + +enum { + USB_STRING_NONE = 0, + USB_STRING_MAN = 1, + USB_STRING_PRODUCT, + USB_STRING_SERIAL, + USB_STRING_MAC_ADDRESS, + USB_STRING_CONFIG_COMPOSITE, + USB_STRING_CONFIG_RNDIS, + USB_STRING_CONFIG_EEM, + USB_STRING_CONFIG_ECM, + USB_STRING_CONFIG_ECM_DEBUG, + USB_STRING_CONFIG_MS, + USB_STRING_INTERFACE_RNDIS, + USB_STRING_INTERFACE_EEM, + USB_STRING_INTERFACE_ECM, + USB_STRING_INTERFACE_ECM_ATTACHED, + USB_STRING_INTERFACE_ECM_DETACHED, + USB_STRING_INTERFACE_SERIAL, + USB_STRING_INTERFACE_MS, + +}; + +enum { + USB_CONFIG_UNCONFIGURED = 0, + + USB_CONFIG_RNDIS = 1, + USB_CONFIG_RNDIS_DEBUG = 1+(1<<7), + + USB_CONFIG_ECM = 2, + USB_CONFIG_ECM_DEBUG = 2+(1<<7), + + USB_CONFIG_EEM = 3, + +#if USB_CONF_STORAGE + USB_CONFIG_MS = 4, +#endif +}; + +#define USB_CONFIG_HAS_DEBUG_PORT(x) ((x==USB_CONFIG_ECM_DEBUG)||(x==USB_CONFIG_RNDIS_DEBUG)) + +//#define USB_CONFIG_COUNT (USB_CONFIG_COUNT_PLUS_ONE-1) +//#define NB_CONFIGURATION USB_CONFIG_COUNT #define NETWORK_NB_INTERFACE 2 #define COMPOSITE_NB_INTERFACE 4 @@ -134,14 +173,14 @@ #define ENDPOINT_NB_2 0x80 | TX_EP #define EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EP_SIZE_2 0x40 //64 byte max size -#define EP_INTERVAL_2 0x00 +#define EP_INTERVAL_2 0x01 // USB Endpoint 2 descriptor //Bulk OUT RX endpoint #define ENDPOINT_NB_3 RX_EP #define EP_ATTRIBUTES_3 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EP_SIZE_3 0x40 //64 byte max size -#define EP_INTERVAL_3 0x00 +#define EP_INTERVAL_3 0x01 /*** CDC Virtual Serial Port ***/ @@ -176,14 +215,14 @@ #define ENDPOINT_NB_5 0x80 | VCP_TX_EP #define EP_ATTRIBUTES_5 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EP_SIZE_5 0x20 -#define EP_INTERVAL_5 0x00 +#define EP_INTERVAL_5 0x01 // USB Endpoint 6 descriptor // Bulk OUT #define ENDPOINT_NB_6 VCP_RX_EP #define EP_ATTRIBUTES_6 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EP_SIZE_6 0x20 -#define EP_INTERVAL_6 0x00 +#define EP_INTERVAL_6 0x01 /*** Mass Storage ***/ @@ -227,61 +266,34 @@ #define EEM_ENDPOINT_NB_1 0x80 | TX_EP #define EEM_EP_ATTRIBUTES_1 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EEM_EP_SIZE_1 0x40 //64 byte max size -#define EEM_EP_INTERVAL_1 0x00 +#define EEM_EP_INTERVAL_1 0x01 // USB Endpoint 2 descriptor // Bulk OUT #define EEM_ENDPOINT_NB_2 RX_EP #define EEM_EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EEM_EP_SIZE_2 0x40 //64 byte max size -#define EEM_EP_INTERVAL_2 0x00 +#define EEM_EP_INTERVAL_2 0x01 + + +/******* ECM Configuration *******/ + +// Interface 0 descriptor +#define ECM_INTERFACE0_NB 0 +#define ECM_ALTERNATE0 0 +#define ECM_NB_ENDPOINT0 2 +#define ECM_INTERFACE0_CLASS 0x02 // CDC ACM Com +#define ECM_INTERFACE0_SUB_CLASS 0x06 // ECM +#define ECM_INTERFACE0_PROTOCOL 0x00 // Empty +#define ECM_INTERFACE0_INDEX 0 + + #define DEVICE_STATUS 0x00 // TBD #define INTERFACE_STATUS 0x00 // TBD #define LANG_ID 0x00 - - - -#define USB_MN_LENGTH 5 -#define USB_MANUFACTURER_NAME \ -{ Usb_unicode('A') \ -, Usb_unicode('t') \ -, Usb_unicode('m') \ -, Usb_unicode('e') \ -, Usb_unicode('l') \ -} - -#define USB_PN_LENGTH 16 -#define USB_PRODUCT_NAME \ -{ Usb_unicode('R') \ - ,Usb_unicode('Z') \ - ,Usb_unicode('R') \ - ,Usb_unicode('A') \ - ,Usb_unicode('V') \ - ,Usb_unicode('E') \ - ,Usb_unicode('N') \ - ,Usb_unicode(' ') \ - ,Usb_unicode('U') \ - ,Usb_unicode('S') \ - ,Usb_unicode('B') \ - ,Usb_unicode(' ') \ - ,Usb_unicode('D') \ - ,Usb_unicode('E') \ - ,Usb_unicode('M') \ - ,Usb_unicode('O') \ -} - -#define USB_SN_LENGTH 0x05 -#define USB_SERIAL_NUMBER \ -{Usb_unicode('1') \ - ,Usb_unicode('.') \ - ,Usb_unicode('0') \ - ,Usb_unicode('.') \ - ,Usb_unicode('0') \ -} - #define LANGUAGE_ID 0x0409 //! Usb Request @@ -373,39 +385,6 @@ typedef struct { } S_usb_language_id; -//_____ U S B M A N U F A C T U R E R D E S C R I P T O R _______________ - - -//struct usb_st_manufacturer -typedef struct { - U8 bLength; // size of this descriptor in bytes - U8 bDescriptorType; // STRING descriptor type - U16 wstring[USB_MN_LENGTH];// unicode characters -} S_usb_manufacturer_string_descriptor; - - -//_____ U S B P R O D U C T D E S C R I P T O R _________________________ - - -//struct usb_st_product -typedef struct { - U8 bLength; // size of this descriptor in bytes - U8 bDescriptorType; // STRING descriptor type - U16 wstring[USB_PN_LENGTH];// unicode characters -} S_usb_product_string_descriptor; - - -//_____ U S B S E R I A L N U M B E R D E S C R I P T O R _____________ - - -//struct usb_st_serial_number -typedef struct { - U8 bLength; // size of this descriptor in bytes - U8 bDescriptorType; // STRING descriptor type - U16 wstring[USB_SN_LENGTH];// unicode characters -} S_usb_serial_number; - - /*_____ U S B I A D _______________________________________________________*/ #define DSC_TYPE_IAD 11 @@ -460,6 +439,79 @@ typedef struct } S_usb_user_configuration_descriptor_network; +/* EEM */ +typedef struct +{ + S_usb_configuration_descriptor cfg; + S_usb_interface_descriptor ifc0; + S_usb_endpoint_descriptor ep1; + S_usb_endpoint_descriptor ep2; +} S_usb_user_configuration_descriptor_eem; + + + + +typedef struct +{ + U8 bLength; + U8 bDescriptorType; + U8 bDescriptorSubtype; + U8 iMACAddress; + U32 bmEthernetStatistics; + U16 wMaxSegmentSize; + U16 wNumberMCFilters; + U8 bNumberPowerFilters; +} S_usb_ethernet_networking_functional_descriptor; + + +/* ECM */ +typedef struct +{ + S_usb_configuration_descriptor cfg; + S_usb_interface_descriptor ifc0; + U8 CS1_INTERFACE[5+5]; + S_usb_ethernet_networking_functional_descriptor fd0; +#if CDC_ECM_USES_INTERRUPT_ENDPOINT + S_usb_endpoint_descriptor ep1; +#endif +#if 0 + S_usb_interface_descriptor ifc1_0; +#endif + S_usb_interface_descriptor ifc1_1; + S_usb_endpoint_descriptor ep2; + S_usb_endpoint_descriptor ep3; +} S_usb_user_configuration_descriptor_ecm; + + +/* ECM + Serial Port */ +typedef struct +{ + S_usb_configuration_descriptor cfg; + S_usb_interface_association_descriptor iad0; + S_usb_interface_descriptor ifc0; + U8 CS1_INTERFACE[5+5]; + S_usb_ethernet_networking_functional_descriptor fd0; +#if CDC_ECM_USES_INTERRUPT_ENDPOINT + S_usb_endpoint_descriptor ep1; +#endif +#if 0 + S_usb_interface_descriptor ifc1_0; +#endif + S_usb_interface_descriptor ifc1_1; + S_usb_endpoint_descriptor ep2; + S_usb_endpoint_descriptor ep3; + + S_usb_interface_association_descriptor iad1; + S_usb_interface_descriptor ifc2; + U8 CS2_INTERFACE[19]; + S_usb_endpoint_descriptor ep4; + S_usb_interface_descriptor ifc3; + S_usb_endpoint_descriptor ep5; + S_usb_endpoint_descriptor ep6; + +} S_usb_user_configuration_descriptor_ecm_debug; + + /* Mass Storage */ typedef struct @@ -471,20 +523,12 @@ typedef struct } S_usb_user_configuration_descriptor_mass; -/* EEM */ -typedef struct -{ - S_usb_configuration_descriptor cfg; - S_usb_interface_descriptor ifc0; - S_usb_endpoint_descriptor ep1; - S_usb_endpoint_descriptor ep2; -} S_usb_user_configuration_descriptor_eem; PGM_VOID_P Usb_get_dev_desc_pointer(void); U8 Usb_get_dev_desc_length(void); -PGM_VOID_P Usb_get_conf_desc_pointer(void) ; -U8 Usb_get_conf_desc_length(void); +PGM_VOID_P Usb_get_conf_desc_pointer(U8 index) ; +U8 Usb_get_conf_desc_length(U8 index); #endif // _USB_USERCONFIG_H_ diff --git a/cpu/avr/dev/usb/usb_drv.c b/cpu/avr/dev/usb/usb_drv.c index 3be5a8911..1b717c490 100644 --- a/cpu/avr/dev/usb/usb_drv.c +++ b/cpu/avr/dev/usb/usb_drv.c @@ -50,6 +50,7 @@ #include "config.h" #include "conf_usb.h" #include "usb_drv.h" +#include //_____ M A C R O S ________________________________________________________ @@ -61,6 +62,102 @@ #if (USB_DEVICE_FEATURE == ENABLED) +#define USB_ENDPOINT_WAIT_TIMEOUT 250 + +U8 usb_endpoint_wait_for_write_enabled() { +#if USB_ENDPOINT_WAIT_TIMEOUT + U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT; + while(timeout) { + if(Is_usb_sof()) { + Usb_ack_sof(); + timeout--; + } +#else + while(1) { +#endif + if(Is_usb_write_enabled()) + return 0; + if((!Is_usb_enabled()) || Is_usb_detached()) + return 1; + if(!Is_usb_endpoint_enabled()) + return 2; + if(Is_usb_endpoint_stall_requested()) + return 3; + } + return 10; +} + +U8 usb_endpoint_wait_for_read_control_enabled() { +#if USB_ENDPOINT_WAIT_TIMEOUT + U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT; + while(timeout) { + if(Is_usb_sof()) { + Usb_ack_sof(); + timeout--; + } +#else + while(1) { +#endif + if(Is_usb_read_control_enabled()) + return 0; + if((!Is_usb_enabled()) || Is_usb_detached()) + return 1; + if(!Is_usb_endpoint_enabled()) + return 2; + if(Is_usb_endpoint_stall_requested()) + return 3; + } + return 10; +} + + +U8 usb_endpoint_wait_for_IN_ready() { +#if USB_ENDPOINT_WAIT_TIMEOUT + U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT; + while(timeout) { + if(Is_usb_sof()) { + Usb_ack_sof(); + timeout--; + } +#else + while(1) { +#endif + if(Is_usb_in_ready()) + return 0; + if((!Is_usb_enabled()) || Is_usb_detached()) + return 1; + if(!Is_usb_endpoint_enabled()) + return 2; + if(Is_usb_endpoint_stall_requested()) + return 3; + } + return 10; +} + + +U8 usb_endpoint_wait_for_receive_out() { +#if USB_ENDPOINT_WAIT_TIMEOUT + U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT; + while(timeout) { + if(Is_usb_sof()) { + Usb_ack_sof(); + timeout--; + } +#else + while(1) { +#endif + if(Is_usb_receive_out()) + return 0; + if((!Is_usb_enabled()) || Is_usb_detached()) + return 1; + if(!Is_usb_endpoint_enabled()) + return 2; + if(Is_usb_endpoint_stall_requested()) + return 3; + } + return 10; +} + //! usb_configure_endpoint. //! //! This function configures an endpoint with the selected type. diff --git a/cpu/avr/dev/usb/usb_drv.h b/cpu/avr/dev/usb/usb_drv.h index cf56d0e75..63abcdbf3 100644 --- a/cpu/avr/dev/usb/usb_drv.h +++ b/cpu/avr/dev/usb/usb_drv.h @@ -160,7 +160,7 @@ typedef enum endpoint_parameter{ep_num, ep_type, ep_direction, ep_size, ep_bank, //! @defgroup Endpoints_configuration Configuration macros for endpoints //! List of the standard macro used to configure pipes and endpoints //! @{ -#define Usb_build_ep_config0(type, dir, nyet) ((type<<6) | (nyet<<1) | (dir)) +#define Usb_build_ep_config0(type, dir, nyet) ((type<<6) /*| (nyet<<1)*/ | (dir)) #define Usb_build_ep_config1(size, bank ) ((size<<4) | (bank<<2) ) #define usb_configure_endpoint(num, type, dir, size, bank, nyet) \ ( Usb_select_endpoint(num), \ @@ -929,6 +929,13 @@ U8 host_determine_pipe_size (U16); void host_disable_all_pipe (void); U8 usb_get_nb_pipe_interrupt (void); +U8 usb_endpoint_wait_for_read_control_enabled(); +U8 usb_endpoint_wait_for_write_enabled(); +U8 usb_endpoint_wait_for_receive_out(); +U8 usb_endpoint_wait_for_IN_ready(); + +#define usb_endpoint_wait_for_read_enabled usb_endpoint_wait_for_write_enabled + #endif // _USB_DRV_H_ /** @} */ diff --git a/cpu/avr/dev/usb/usb_specific_request.c b/cpu/avr/dev/usb/usb_specific_request.c index 912e854df..e2b2e556c 100644 --- a/cpu/avr/dev/usb/usb_specific_request.c +++ b/cpu/avr/dev/usb/usb_specific_request.c @@ -50,10 +50,12 @@ #include "usb_descriptors.h" #include "usb_specific_request.h" #include "rndis/rndis_protocol.h" +#include "rndis/cdc_ecm.h" #include "serial/uart_usb_lib.h" #include "storage/ctrl_access.h" #include "uip.h" #include +#include #include //_____ M A C R O S ________________________________________________________ @@ -85,30 +87,44 @@ Bool usb_user_read_request(U8 type, U8 request) { U16 wLength; - //Both protocols have two bytes we throw away - Usb_read_byte(); - Usb_read_byte(); - switch(request) { case SEND_ENCAPSULATED_COMMAND: + Usb_read_byte(); + Usb_read_byte(); Usb_read_byte();//wIndex LSB Usb_read_byte();//wIndex MSB LSB(wLength) = Usb_read_byte(); MSB(wLength) = Usb_read_byte(); - return send_encapsulated_command(wLength); + if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG)) + return rndis_send_encapsulated_command(wLength); + else + return FALSE; break; case GET_ENCAPSULATED_COMMAND: + Usb_read_byte(); + Usb_read_byte(); Usb_read_byte();//wIndex LSB Usb_read_byte();//wIndex MSB LSB(wLength) = Usb_read_byte(); MSB(wLength) = Usb_read_byte(); - return get_encapsulated_command(); + if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG)) + return rndis_get_encapsulated_command(); + else + return FALSE; break; + case SET_ETHERNET_PACKET_FILTER: + if((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG)) { + cdc_ecm_set_ethernet_packet_filter(); + return TRUE; + } else + return FALSE; + break; + #if USB_CONF_STORAGE case MASS_STORAGE_RESET: Usb_ack_receive_setup(); @@ -130,18 +146,34 @@ Bool usb_user_read_request(U8 type, U8 request) /* We don't have a real serial port - so these aren't applicable. We advertise that we support nothing, so shouldn't get them anyway */ case GET_LINE_CODING: - cdc_get_line_coding(); - return TRUE; + Usb_read_byte(); + Usb_read_byte(); + if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) { + cdc_get_line_coding(); + return TRUE; + } else { + return FALSE; + } break; case SET_LINE_CODING: - cdc_set_line_coding(); - return TRUE; + Usb_read_byte(); + Usb_read_byte(); + if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) { + cdc_set_line_coding(); + return TRUE; + } else { + return FALSE; + } break; case SET_CONTROL_LINE_STATE: - cdc_set_control_line_state(); - return TRUE; + if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) { + cdc_set_control_line_state(); + return TRUE; + } else { + return FALSE; + } break; #endif /* USB_CONF_CDC */ default: @@ -174,21 +206,6 @@ Bool usb_user_get_descriptor(U8 type, U8 string) pbuffer = &(usb_user_language_id.bLength); return TRUE; break; - case MAN_INDEX: - data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor); - pbuffer = &(usb_user_manufacturer_string_descriptor.bLength); - return TRUE; - break; - case PROD_INDEX: - data_to_transfer = sizeof (usb_user_product_string_descriptor); - pbuffer = &(usb_user_product_string_descriptor.bLength); - return TRUE; - break; - case SN_INDEX: - data_to_transfer = sizeof (usb_user_serial_number); - pbuffer = &(usb_user_serial_number.bLength); - return TRUE; - break; default: return FALSE; } @@ -198,6 +215,94 @@ Bool usb_user_get_descriptor(U8 type, U8 string) return FALSE; } +static char itoh(unsigned char i) { + char ret; + ret = pgm_read_byte_near(PSTR("0123456789abcdef")+(i&0xF)); + return ret; +} +const char* usb_user_get_string_sram(U8 string_type) { + static char serial[13]; + uint8_t i; + + switch (string_type) + { + case USB_STRING_SERIAL: + case USB_STRING_MAC_ADDRESS: + { + uint8_t mac_address[6]; + usb_eth_get_mac_address(mac_address); + + for(i=0;i<6;i++) { + serial[i*2] = itoh(mac_address[i]>>4); + serial[i*2+1] = itoh(mac_address[i]); + } + } + break; + default: + serial[0] = 0; + break; + } + + return serial; +} + +PGM_P usb_user_get_string(U8 string_type) { + switch (string_type) + { + case USB_STRING_MAN: + return PSTR("Atmel"); + + case USB_STRING_PRODUCT: + return PSTR("Jackdaw 6LoWPAN Adaptor"); + + case USB_STRING_CONFIG_COMPOSITE: + return PSTR("RNDIS+Debug"); + + case USB_STRING_CONFIG_RNDIS: + case USB_STRING_INTERFACE_RNDIS: + return PSTR("RNDIS"); + + case USB_STRING_CONFIG_EEM: + case USB_STRING_INTERFACE_EEM: + return PSTR("CDC-EEM"); + + case USB_STRING_CONFIG_ECM: + case USB_STRING_INTERFACE_ECM: + return PSTR("CDC-ECM"); + + case USB_STRING_CONFIG_ECM_DEBUG: + return PSTR("CDC-ECM+DEBUG"); + + case USB_STRING_INTERFACE_SERIAL: + return PSTR("Debug Port"); +/* + case USB_STRING_INTERFACE_ECM_ATTACHED: + return PSTR("Attached"); + case USB_STRING_INTERFACE_ECM_DETACHED: + return PSTR("Detached"); +*/ +#if USB_CONF_STORAGE + case USB_STRING_CONFIG_MS: + case USB_STRING_INTERFACE_MS: + return PSTR("Mass Storage"); +#endif + +/* + // This is now handled by usb_user_get_string_sram. + case USB_STRING_SERIAL: + return PSTR("JD01"); + + case USB_STRING_MAC_ADDRESS: + return PSTR("021213141516"); + +*/ + + + default: + return NULL; + } +} + //! usb_user_endpoint_init. //! @@ -206,115 +311,54 @@ Bool usb_user_get_descriptor(U8 type, U8 string) //! @param conf_nb Not used void usb_user_endpoint_init(U8 conf_nb) { + if(USB_CONFIG_HAS_DEBUG_PORT(conf_nb)) { + uart_usb_configure_endpoints(); + } - /* If we use RNDIS endpoints */ - if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) { + switch(conf_nb) { + case USB_CONFIG_ECM: + case USB_CONFIG_ECM_DEBUG: + cdc_ecm_configure_endpoints(); + break; - usb_configure_endpoint(INT_EP, \ - TYPE_INTERRUPT, \ - DIRECTION_IN, \ - SIZE_64, \ - ONE_BANK, \ - NYET_ENABLED); + case USB_CONFIG_RNDIS_DEBUG: + case USB_CONFIG_RNDIS: + rndis_configure_endpoints(); + break; + case USB_CONFIG_EEM: + cdc_ecm_configure_endpoints(); - usb_configure_endpoint(TX_EP, \ - TYPE_BULK, \ - DIRECTION_IN, \ - SIZE_64, \ - TWO_BANKS, \ - NYET_ENABLED); + break; +#if USB_CONF_STORAGE + case USB_CONFIG_MS: + usb_configure_endpoint(VCP_INT_EP, \ + TYPE_INTERRUPT, \ + DIRECTION_IN, \ + SIZE_32, \ + ONE_BANK, \ + NYET_ENABLED); - usb_configure_endpoint(RX_EP, \ - TYPE_BULK, \ - DIRECTION_OUT, \ - SIZE_64, \ - TWO_BANKS, \ - NYET_ENABLED); + usb_configure_endpoint(VCP_TX_EP, \ + TYPE_BULK, \ + DIRECTION_IN, \ + SIZE_32, \ + TWO_BANKS, \ + NYET_ENABLED); - } - - /* If we use virtual comm port (VCP) endpoints */ - if (usb_mode == rndis_debug) { - usb_configure_endpoint(VCP_INT_EP, \ - TYPE_INTERRUPT, \ - DIRECTION_IN, \ - SIZE_32, \ - ONE_BANK, \ - NYET_ENABLED); - - usb_configure_endpoint(VCP_TX_EP, \ - TYPE_BULK, \ - DIRECTION_IN, \ - SIZE_32, \ - TWO_BANKS, \ - NYET_ENABLED); - - usb_configure_endpoint(VCP_RX_EP, \ - TYPE_BULK, \ - DIRECTION_OUT, \ - SIZE_32, \ - TWO_BANKS, \ - NYET_ENABLED); - } - - /* If we use mass storage endpoints */ - if (usb_mode == mass_storage) { - - usb_configure_endpoint(MS_IN_EP, \ - TYPE_BULK, \ - DIRECTION_IN, \ - SIZE_64, \ - ONE_BANK, \ - NYET_ENABLED); - - usb_configure_endpoint(MS_OUT_EP, \ - TYPE_BULK, \ - DIRECTION_OUT, \ - SIZE_64, \ - ONE_BANK, \ - NYET_ENABLED); - } - - if (usb_mode == eem ) { - usb_configure_endpoint(TX_EP, \ - TYPE_BULK, \ - DIRECTION_IN, \ - SIZE_64, \ - TWO_BANKS, \ - NYET_ENABLED); - - usb_configure_endpoint(RX_EP, \ - TYPE_BULK, \ - DIRECTION_OUT, \ - SIZE_64, \ - TWO_BANKS, \ - NYET_ENABLED); - } - - - - if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) { - Usb_reset_endpoint(INT_EP); - Usb_reset_endpoint(TX_EP); - Usb_reset_endpoint(RX_EP); - } - - if (usb_mode == rndis_debug){ - Usb_reset_endpoint(VCP_INT_EP); - Usb_reset_endpoint(VCP_TX_EP); - Usb_reset_endpoint(VCP_RX_EP); - } - - if (usb_mode == mass_storage) { - Usb_reset_endpoint(VCP_TX_EP); - Usb_reset_endpoint(VCP_RX_EP); - } - - if (usb_mode == eem){ - Usb_reset_endpoint(TX_EP); - Usb_reset_endpoint(RX_EP); - } + usb_configure_endpoint(VCP_RX_EP, \ + TYPE_BULK, \ + DIRECTION_OUT, \ + SIZE_32, \ + TWO_BANKS, \ + NYET_ENABLED); + Usb_reset_endpoint(VCP_INT_EP); + Usb_reset_endpoint(VCP_TX_EP); + Usb_reset_endpoint(VCP_RX_EP); + break; +#endif + } + Led0_on(); } #if USB_CONF_CDC @@ -337,12 +381,7 @@ void cdc_get_line_coding(void) Usb_write_byte(line_coding.bParityType); Usb_write_byte(line_coding.bDataBits); - Usb_send_control_in(); - while(!(Is_usb_read_control_enabled())); - //Usb_clear_tx_complete(); - - while(!Is_usb_receive_out()); - Usb_ack_receive_out(); + Usb_send_control_in(); } @@ -352,19 +391,20 @@ void cdc_get_line_coding(void) //! void cdc_set_line_coding (void) { - Usb_ack_receive_setup(); - while (!(Is_usb_receive_out())); - LSB0(line_coding.dwDTERate) = Usb_read_byte(); - LSB1(line_coding.dwDTERate) = Usb_read_byte(); - LSB2(line_coding.dwDTERate) = Usb_read_byte(); - LSB3(line_coding.dwDTERate) = Usb_read_byte(); - line_coding.bCharFormat = Usb_read_byte(); - line_coding.bParityType = Usb_read_byte(); - line_coding.bDataBits = Usb_read_byte(); - Usb_ack_receive_out(); + Usb_ack_receive_setup(); + if(usb_endpoint_wait_for_receive_out()==0) { + LSB0(line_coding.dwDTERate) = Usb_read_byte(); + LSB1(line_coding.dwDTERate) = Usb_read_byte(); + LSB2(line_coding.dwDTERate) = Usb_read_byte(); + LSB3(line_coding.dwDTERate) = Usb_read_byte(); + line_coding.bCharFormat = Usb_read_byte(); + line_coding.bParityType = Usb_read_byte(); + line_coding.bDataBits = Usb_read_byte(); + Usb_ack_receive_out(); - Usb_send_control_in(); // send a ZLP for STATUS phase - while(!(Is_usb_read_control_enabled())); + Usb_send_control_in(); // send a ZLP for STATUS phase + usb_endpoint_wait_for_read_control_enabled(); + } } //! cdc_set_control_line_state. @@ -375,8 +415,27 @@ void cdc_set_line_coding (void) //! void cdc_set_control_line_state (void) { + U8 controlLineState = Usb_read_byte(); + U8 dummy = Usb_read_byte(); + U8 interface = Usb_read_byte(); + Usb_ack_receive_setup(); Usb_send_control_in(); - while(!(Is_usb_read_control_enabled())); + usb_endpoint_wait_for_read_control_enabled(); + + if(interface == INTERFACE2_NB) { + uart_usb_set_control_line_state(controlLineState); + } } #endif /* USB_CONF_CDC */ + +Bool usb_user_set_alt_interface(U8 interface, U8 alt_setting) { + return FALSE; + if((interface==ECM_INTERFACE0_NB) && ((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG))) { + // The alt_setting in this case corresponds to + // if the interface is enabled or not. + usb_eth_set_active(alt_setting); + } + return TRUE; +} + diff --git a/cpu/avr/dev/usb/usb_specific_request.h b/cpu/avr/dev/usb/usb_specific_request.h index 14fdb81e5..cbbecf327 100644 --- a/cpu/avr/dev/usb/usb_specific_request.h +++ b/cpu/avr/dev/usb/usb_specific_request.h @@ -65,9 +65,6 @@ extern FLASH S_usb_device_descriptor usb_dev_desc_network; extern FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite; extern FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network; extern FLASH S_usb_device_qualifier_descriptor usb_qual_desc; -extern FLASH S_usb_manufacturer_string_descriptor usb_user_manufacturer_string_descriptor; -extern FLASH S_usb_product_string_descriptor usb_user_product_string_descriptor; -extern FLASH S_usb_serial_number usb_user_serial_number; extern FLASH S_usb_language_id usb_user_language_id; @@ -76,6 +73,10 @@ extern FLASH S_usb_language_id usb_user_language_id; Bool usb_user_read_request(U8, U8); Bool usb_user_get_descriptor(U8 , U8); void usb_user_endpoint_init(U8); +Bool usb_user_set_alt_interface(U8 interface, U8 alt_setting); + +PGM_P usb_user_get_string(U8 string_type); +const char* usb_user_get_string_sram(U8 string_type); void cdc_get_line_coding(); void cdc_set_line_coding(); diff --git a/cpu/avr/dev/usb/usb_standard_request.c b/cpu/avr/dev/usb/usb_standard_request.c index fee58f6f7..20e493f42 100644 --- a/cpu/avr/dev/usb/usb_standard_request.c +++ b/cpu/avr/dev/usb/usb_standard_request.c @@ -52,11 +52,14 @@ #include "usb_drv.h" #include "usb_descriptors.h" #include "usb_specific_request.h" +#include //_____ M A C R O S ________________________________________________________ //_____ D E F I N I T I O N ________________________________________________ +#define PRINTF printf +#define PRINTF_P printf_P //_____ P R I V A T E D E C L A R A T I O N ______________________________ @@ -123,43 +126,43 @@ void usb_process_request(void) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { usb_get_descriptor(); } - else { usb_user_read_request(bmRequestType, bmRequest); } + else goto user_read; break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); } - else { usb_user_read_request(bmRequestType, bmRequest); } + else goto user_read; break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); } - else { usb_user_read_request(bmRequestType, bmRequest); } + else goto user_read; break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); } - else { usb_user_read_request(bmRequestType, bmRequest); } + else goto user_read; break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); } - else { usb_user_read_request(bmRequestType, bmRequest); } + else goto user_read; break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); } - else { usb_user_read_request(bmRequestType, bmRequest); } + else goto user_read; break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); } - else { usb_user_read_request(bmRequestType, bmRequest); } + else goto user_read; break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); } - else { usb_user_read_request(bmRequestType, bmRequest); } + else goto user_read; break; @@ -170,14 +173,23 @@ void usb_process_request(void) case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< un-supported request => call to user read request - if(usb_user_read_request(bmRequestType, bmRequest) == FALSE) - { - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); - return; - } + user_read: + usb_user_read_request(bmRequestType, bmRequest); break; } + + Usb_select_endpoint(EP_CONTROL); + + // If the receive setup flag hasn't been cleared + // by this point then we can assume that we didn't + // support this request and should stall. + if(Is_usb_receive_setup()) + Usb_enable_stall_handshake(); + + // Clear some flags. + Usb_ack_receive_setup(); + Usb_ack_receive_out(); + Usb_ack_in_ready(); } //! usb_set_address. @@ -214,26 +226,205 @@ U8 configuration_number; configuration_number = Usb_read_byte(); - if (configuration_number <= NB_CONFIGURATION) - { - Usb_ack_receive_setup(); - usb_configuration_nb = configuration_number; - } - else - { - //!< keep that order (set StallRq/clear RxSetup) or a - //!< OUT request following the SETUP may be acknowledged - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); - return; - } + // TODO: Verify configuration_number! + Usb_ack_receive_setup(); + usb_configuration_nb = configuration_number; Usb_send_control_in(); //!< send a ZLP for STATUS phase + while(!Is_usb_in_ready()); usb_user_endpoint_init(usb_configuration_nb); //!< endpoint configuration Usb_set_configuration_action(); } + + + + +void usb_get_string_descriptor_sram(U8 string_type) { + U16 requested_length; + U8 dummy; + const char* user_str; + + user_str = usb_user_get_string_sram(string_type); + + dummy = Usb_read_byte(); //!< don't care of wIndex field + dummy = Usb_read_byte(); + requested_length = Usb_read_byte(); //!< read wLength + requested_length |= Usb_read_byte()<<8; + + if(!user_str) + return; + + const U8 actual_descriptor_size = 2+strlen(user_str)*2; + + if (requested_length > actual_descriptor_size) { + zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0); + requested_length = actual_descriptor_size; + } + + Usb_ack_receive_setup() ; //!< clear the receive setup flag + + if(usb_endpoint_wait_for_read_control_enabled()!=0) { + Usb_enable_stall_handshake(); + return; + } + + // Output the length + Usb_write_byte(actual_descriptor_size); + + // Output the type + Usb_write_byte(STRING_DESCRIPTOR); + + requested_length -= 2; + U8 nb_byte = 2; + + if(!requested_length) { + Usb_send_control_in(); + } + + while((requested_length != 0) && (!Is_usb_receive_out())) + { + if(usb_endpoint_wait_for_read_control_enabled()!=0) { + Usb_enable_stall_handshake(); + break; + } + + while(requested_length != 0) //!< Send data until necessary + { + if(nb_byte==EP_CONTROL_LENGTH) //!< Check endpoint 0 size + { + nb_byte=0; + break; + } + + Usb_write_byte(*user_str); + Usb_write_byte(0); + user_str++; + requested_length -=2; + nb_byte+=2; + } + Usb_send_control_in(); + } + +bail: + if(Is_usb_receive_out()) { + //! abort from Host + Usb_ack_receive_out(); + return; + } + + if(zlp == TRUE) { + if(usb_endpoint_wait_for_read_control_enabled()!=0) { + Usb_enable_stall_handshake(); + return; + } + Usb_send_control_in(); + } + + usb_endpoint_wait_for_receive_out(); + Usb_ack_receive_out(); +} + + +void usb_get_string_descriptor(U8 string_type) { + U16 requested_length; + U8 dummy; + PGM_P user_str; + + user_str = usb_user_get_string(string_type); + + if(!user_str) { + usb_get_string_descriptor_sram(string_type); + return; + } + + dummy = Usb_read_byte(); //!< don't care of wIndex field + dummy = Usb_read_byte(); + requested_length = Usb_read_byte(); //!< read wLength + requested_length |= Usb_read_byte()<<8; + + + const U8 actual_descriptor_size = 2+strlen_P(user_str)*2; + + if (requested_length > actual_descriptor_size) { + zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0); + requested_length = actual_descriptor_size; + } + + Usb_ack_receive_setup() ; //!< clear the receive setup flag + + if(usb_endpoint_wait_for_read_control_enabled()!=0) { + Usb_enable_stall_handshake(); + return; + } + U8 nb_byte = 0; + + // Output the length + if(requested_length) { + Usb_write_byte(actual_descriptor_size); + requested_length--; + nb_byte++; + } + + // Output the type + if(requested_length) { + Usb_write_byte(STRING_DESCRIPTOR); + requested_length--; + nb_byte++; + } + + if(!requested_length) { + Usb_send_control_in(); + } + + while((requested_length != 0) && (!Is_usb_receive_out())) + { + if(usb_endpoint_wait_for_read_control_enabled()!=0) { + Usb_enable_stall_handshake(); + break; + } + + while(requested_length != 0) //!< Send data until necessary + { + if(nb_byte==EP_CONTROL_LENGTH) { //!< Check endpoint 0 size + nb_byte=0; + break; + } + + Usb_write_byte(pgm_read_byte_near((unsigned int)user_str++)); + requested_length--; + nb_byte++; + if(requested_length) { + Usb_write_byte(0); + requested_length--; + nb_byte++; + } + } + Usb_send_control_in(); + } + +bail: + + if(Is_usb_receive_out()) { + //! abort from Host + Usb_ack_receive_out(); + return; + } + + if(zlp == TRUE) { + if(usb_endpoint_wait_for_read_control_enabled()!=0) { + Usb_enable_stall_handshake(); + return; + } + Usb_send_control_in(); + } + + usb_endpoint_wait_for_receive_out(); + Usb_ack_receive_out(); +} + + //! usb_get_descriptor. //! //! This function manages the GET DESCRIPTOR request. The device descriptor, @@ -246,91 +437,93 @@ U8 configuration_number; //! void usb_get_descriptor(void) { -U8 LSBwLength, MSBwLength; -U8 descriptor_type ; -U8 string_type ; -U8 dummy; -U8 nb_byte; + U8 LSBwLength, MSBwLength; + U8 descriptor_type ; + U8 string_type ; + U8 dummy; - zlp = FALSE; /* no zero length packet */ - string_type = Usb_read_byte(); /* read LSB of wValue */ - descriptor_type = Usb_read_byte(); /* read MSB of wValue */ + zlp = FALSE; /* no zero length packet */ + string_type = Usb_read_byte(); /* read LSB of wValue */ + descriptor_type = Usb_read_byte(); /* read MSB of wValue */ - dummy = Usb_read_byte(); //!< don't care of wIndex field - dummy = Usb_read_byte(); - LSBwLength = Usb_read_byte(); //!< read wLength - MSBwLength = Usb_read_byte(); + switch (descriptor_type) + { + case DEVICE_DESCRIPTOR: + data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor); + pbuffer = Usb_get_dev_desc_pointer(); + break; + case CONFIGURATION_DESCRIPTOR: + data_to_transfer = Usb_get_conf_desc_length(string_type); //!< sizeof (usb_user_configuration_descriptor); + pbuffer = Usb_get_conf_desc_pointer(string_type); + break; + case STRING_DESCRIPTOR: + if(string_type!=LANG_ID) { + usb_get_string_descriptor(string_type); + return; + } + default: + dummy = Usb_read_byte(); + dummy = Usb_read_byte(); + dummy = Usb_read_byte(); + dummy = Usb_read_byte(); + if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE ) + return; + break; + } - switch (descriptor_type) - { - case DEVICE_DESCRIPTOR: - data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor); - pbuffer = Usb_get_dev_desc_pointer(); - break; - case CONFIGURATION_DESCRIPTOR: - data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor); - pbuffer = Usb_get_conf_desc_pointer(); - break; - default: - if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE ) - { - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); - return; - } - break; - } + dummy = Usb_read_byte(); //!< don't care of wIndex field + dummy = Usb_read_byte(); + LSBwLength = Usb_read_byte(); //!< read wLength + MSBwLength = Usb_read_byte(); + Usb_ack_receive_setup() ; //!< clear the receive setup flag - Usb_ack_receive_setup() ; //!< clear the receive setup flag + if ((LSBwLength > data_to_transfer) || (MSBwLength)) { + if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } + else { zlp = FALSE; } //!< no need of zero length packet - if ((LSBwLength > data_to_transfer) || (MSBwLength)) - { - if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } - else { zlp = FALSE; } //!< no need of zero length packet + LSBwLength = data_to_transfer; + MSBwLength = 0x00; + } else { + data_to_transfer = LSBwLength; //!< send only requested number of data + } + + while((data_to_transfer != 0) && (!Is_usb_receive_out())) { + U8 nb_byte = 0; + if(usb_endpoint_wait_for_read_control_enabled()!=0) { + Usb_enable_stall_handshake(); + break; + } - LSBwLength = data_to_transfer; - MSBwLength = 0x00; - } - else - { - data_to_transfer = LSBwLength; //!< send only requested number of data - } + //! Send data until necessary + while(data_to_transfer != 0) { +// if(Is_usb_write_enabled()) //!< Check endpoint 0 size + if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size + break; + Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++)); + data_to_transfer --; - while((data_to_transfer != 0) && (!Is_usb_receive_out())) - { - while(!Is_usb_read_control_enabled()); + } + Usb_send_control_in(); + } - nb_byte=0; - while(data_to_transfer != 0) //!< Send data until necessary - { - if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size - { - break; - } + if(Is_usb_receive_out()) { + //! abort from Host + Usb_ack_receive_out(); + return; + } + + if(zlp == TRUE) { + if(usb_endpoint_wait_for_read_control_enabled()!=0) { + Usb_enable_stall_handshake(); + return; + } + Usb_send_control_in(); + } -//#ifndef AVRGCC -// Usb_write_byte(*pbuffer++); -//#else // AVRGCC does not support point to PGM space - //#warning AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory - Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++)); -//#endif - data_to_transfer --; - - } - Usb_send_control_in(); - } - - if(Is_usb_receive_out()) { Usb_ack_receive_out(); return; } //!< abort from Host - if(zlp == TRUE) - { - while(!Is_usb_read_control_enabled()); - Usb_send_control_in(); - } - - while(!Is_usb_receive_out()); - Usb_ack_receive_out(); + usb_endpoint_wait_for_receive_out(); + Usb_ack_receive_out(); } //! usb_get_configuration. @@ -345,9 +538,9 @@ void usb_get_configuration(void) Usb_ack_receive_setup(); Usb_write_byte(usb_configuration_nb); - Usb_ack_in_ready(); + Usb_send_control_in(); - while( !Is_usb_receive_out() ); + usb_endpoint_wait_for_receive_out(); Usb_ack_receive_out(); } @@ -390,7 +583,7 @@ U8 dummy; Usb_write_byte(0x00); Usb_send_control_in(); - while( !Is_usb_receive_out() ); + usb_endpoint_wait_for_receive_out(); Usb_ack_receive_out(); } @@ -409,10 +602,6 @@ U8 dummy; if (bmRequestType == INTERFACE_TYPE) { - //!< keep that order (set StallRq/clear RxSetup) or a - //!< OUT request following the SETUP may be acknowledged - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); return; } else if (bmRequestType == ENDPOINT_TYPE) @@ -426,8 +615,6 @@ U8 dummy; if (wIndex == EP_CONTROL) { - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); return; } @@ -443,15 +630,11 @@ U8 dummy; else { Usb_select_endpoint(EP_CONTROL); - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); return; } } else { - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); return; } } @@ -471,18 +654,10 @@ U8 dummy; if (bmRequestType == ZERO_TYPE) { - //!< keep that order (set StallRq/clear RxSetup) or a - //!< OUT request following the SETUP may be acknowledged - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); return; } else if (bmRequestType == INTERFACE_TYPE) { - //!< keep that order (set StallRq/clear RxSetup) or a - //!< OUT request following the SETUP may be acknowledged - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); return; } else if (bmRequestType == ENDPOINT_TYPE) @@ -507,19 +682,15 @@ U8 dummy; endpoint_status[wIndex] = 0x00; Usb_ack_receive_setup(); Usb_send_control_in(); + } else { - Usb_select_endpoint(EP_CONTROL); - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); return; } } else { - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); return; } } @@ -533,8 +704,7 @@ U8 dummy; //! void usb_get_interface (void) { - Usb_enable_stall_handshake(); - Usb_ack_receive_setup(); + // Not yet implemented. } //! usb_set_interface. @@ -545,7 +715,21 @@ void usb_get_interface (void) //! void usb_set_interface (void) { - Usb_ack_receive_setup(); - Usb_send_control_in(); //!< send a ZLP for STATUS phase - while(!Is_usb_in_ready()); + U8 alt_setting; + U8 dummy; + U8 interface; + + alt_setting = Usb_read_byte(); + dummy = Usb_read_byte(); + interface = Usb_read_byte(); + + if(usb_user_set_alt_interface(interface, alt_setting)) { + Usb_ack_receive_setup(); + Usb_send_control_in(); //!< send a ZLP for STATUS phase + while(!Is_usb_in_ready()); + + usb_endpoint_wait_for_receive_out(); + Usb_ack_receive_out(); + } + } diff --git a/cpu/avr/dev/usb/usb_task.c b/cpu/avr/dev/usb/usb_task.c index f3952d5e9..94c365478 100644 --- a/cpu/avr/dev/usb/usb_task.c +++ b/cpu/avr/dev/usb/usb_task.c @@ -166,53 +166,44 @@ void usb_start_device (void) */ static void pollhandler(void) { + /* Check for setup packets */ + Usb_select_endpoint(EP_CONTROL); + if (Is_usb_receive_setup()) { + usb_process_request(); + } + /* The previous call might have requested we send + out something to the RNDIS interrupt endpoint */ + if (schedule_interrupt) { + Usb_select_endpoint(INT_EP); - //RNDIS needs a delay where this isn't called, as it will switch endpoints - //and screw up the data transfers - if (!usb_busy) { + //Linux is a bunch of lies, and won't read + //the interrupt endpoint. Hence if this isn't ready just exit + //while(!Is_usb_write_enabled()); - /* Check for setup packets */ - Usb_select_endpoint(EP_CONTROL); - if (Is_usb_receive_setup()) { - usb_process_request(); + if (Is_usb_write_enabled()) { + + // Only valid interrupt is: + // 0x00000001 0x00000000 + // + Usb_write_byte(0x01); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + Usb_write_byte(0x00); + + //Send back + Usb_send_in(); + + schedule_interrupt = 0; } + } - /* The previous call might have requested we send - out something to the RNDIS interrupt endpoint */ - if (schedule_interrupt) { - Usb_select_endpoint(INT_EP); - - //Linux is a bunch of lies, and won't read - //the interrupt endpoint. Hence if this isn't ready just exit - //while(!Is_usb_write_enabled()); - - if (Is_usb_write_enabled()) { - - // Only valid interrupt is: - // 0x00000001 0x00000000 - // - Usb_write_byte(0x01); - Usb_write_byte(0x00); - Usb_write_byte(0x00); - Usb_write_byte(0x00); - Usb_write_byte(0x00); - Usb_write_byte(0x00); - Usb_write_byte(0x00); - Usb_write_byte(0x00); - - //Send back - Usb_send_in(); - - schedule_interrupt = 0; - } - } - - } - - - /* Continue polling */ - process_poll(&usb_process); + /* Continue polling */ + process_poll(&usb_process); } /** diff --git a/cpu/avr/radio/rf230bb/rf230bb.c b/cpu/avr/radio/rf230bb/rf230bb.c index a21dc17b1..1822394b7 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.c +++ b/cpu/avr/radio/rf230bb/rf230bb.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * @(#)$Id: rf230bb.c,v 1.11 2010/06/18 15:44:53 dak664 Exp $ + * @(#)$Id: rf230bb.c,v 1.12 2010/09/17 21:59:09 dak664 Exp $ */ /* * This code is almost device independent and should be easy to port. @@ -56,20 +56,6 @@ #include "net/rime/rimestats.h" #include "net/netstack.h" -#if JACKDAW -#include "sicslow_ethernet.h" -#include "uip.h" -#include "uip_arp.h" //For ethernet header structure -#define ETHBUF(x) ((struct uip_eth_hdr *)x) -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) - /* 6lowpan max size + ethernet header size + 1 */ -static uint8_t raw_buf[127+ UIP_LLH_LEN +1]; -extern uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan); -extern rimeaddr_t macLongAddr; -#include "rndis/rndis_task.h" -#endif - - #include "sys/timetable.h" #define WITH_SEND_CCA 0 @@ -91,17 +77,19 @@ extern rimeaddr_t macLongAddr; #define RF230_CONF_AUTOACK 1 #endif /* RF230_CONF_AUTOACK */ +#if RF230_CONF_AUTOACK +static bool is_promiscuous; +#endif + #ifndef RF230_CONF_AUTORETRIES #define RF230_CONF_AUTORETRIES 2 #endif /* RF230_CONF_AUTOACK */ //Automatic and manual CRC both append 2 bytes to packets -#if RF230_CONF_CHECKSUM +#if RF230_CONF_CHECKSUM || defined(RF230BB_HOOK_TX_PACKET) #include "lib/crc16.h" -#define CHECKSUM_LEN 2 -#else -#define CHECKSUM_LEN 2 #endif /* RF230_CONF_CHECKSUM */ +#define CHECKSUM_LEN 2 #define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN) @@ -212,7 +200,7 @@ const struct radio_driver rf230_driver = }; uint8_t RF230_receive_on,RF230_sleeping; -static int channel; +static uint8_t channel; /* Received frames are buffered to rxframe in the interrupt routine in hal.c */ hal_rx_frame_t rxframe; @@ -424,6 +412,33 @@ radio_set_trx_state(uint8_t new_state) return set_state_status; } +void +rf230_set_promiscuous_mode(bool isPromiscuous) { + if(isPromiscuous) { + is_promiscuous = true; +#if RF230_CONF_AUTOACK + radio_set_trx_state(RX_ON); +#endif + } else { + is_promiscuous = false; +#if RF230_CONF_AUTOACK + radio_set_trx_state(RX_AACK_ON); +#endif + } +} + +bool +rf230_is_ready_to_send() { + switch(radio_get_trx_state()) { + case BUSY_TX: + case BUSY_TX_ARET: + return false; + } + + return true; +} + + static void flushrx(void) { @@ -436,20 +451,9 @@ static void on(void) { ENERGEST_ON(ENERGEST_TYPE_LISTEN); -#if JACKDAW -//blue=0 red=1 green=2 yellow=3 -#define Led0_on() (PORTD |= 0x80) -#define Led1_on() (PORTD &= ~0x20) -#define Led2_on() (PORTE &= ~0x80) -#define Led3_on() (PORTE &= ~0x40) -#define Led0_off() (PORTD &= ~0x80) -#define Led1_off() (PORTD |= 0x20) -#define Led2_off() (PORTE |= 0x80) -#define Led3_off() (PORTE |= 0x40) - Led1_on(); -#else -// PRINTSHORT("o"); -// PRINTF("on\n"); + +#ifdef RF230BB_HOOK_RADIO_ON + RF230BB_HOOK_RADIO_ON(); #endif if (RF230_sleeping) { @@ -461,7 +465,7 @@ on(void) rf230_waitidle(); #if RF230_CONF_AUTOACK - radio_set_trx_state(RX_AACK_ON); + radio_set_trx_state(is_promiscuous?RX_ON:RX_AACK_ON); #else radio_set_trx_state(RX_ON); #endif @@ -475,10 +479,8 @@ off(void) // rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); RF230_receive_on = 0; -#if JACKDAW - Led1_off(); -#else -// PRINTSHORT("f"); +#ifdef RF230BB_HOOK_RADIO_OFF + RF230BB_HOOK_RADIO_OFF(); #endif // DEBUGFLOW('F'); @@ -581,7 +583,7 @@ rf230_init(void) return 1; } /*---------------------------------------------------------------------------*/ -static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH]; +static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH+AUX_LEN]; static int rf230_transmit(unsigned short payload_len) { @@ -711,6 +713,7 @@ rf230_transmit(unsigned short payload_len) static int rf230_prepare(const void *payload, unsigned short payload_len) { + int ret = 0; uint8_t total_len,*pbuf; #if RF230_CONF_TIMESTAMPS struct timestamp timestamp; @@ -736,8 +739,12 @@ rf230_prepare(const void *payload, unsigned short payload_len) if (total_len > RF230_MAX_TX_FRAME_LENGTH){ #if RADIOSTATS RF230_sendfail++; -#endif - return -1; +#endif +#if DEBUG + printf_P(PSTR("rf230_prepare: packet too large (%d, max: %d)\n"),total_len,RF230_MAX_TX_FRAME_LENGTH); +#endif + ret = -1; + goto bail; } pbuf=&buffer[0]; memcpy(pbuf,payload,payload_len); @@ -755,66 +762,46 @@ rf230_prepare(const void *payload, unsigned short payload_len) pbuf+=TIMESTAMP_LEN; #endif /* RF230_CONF_TIMESTAMPS */ /*------------------------------------------------------------*/ -/* If jackdaw report frame to ethernet interface */ -#if JACKDAW -// mac_logTXtoEthernet(¶ms, &result); - if (usbstick_mode.raw != 0) { - uint8_t sendlen; - /* Get the raw frame */ - memcpy(&raw_buf[UIP_LLH_LEN], buffer, total_len); - sendlen = total_len; - - /* Setup generic ethernet stuff */ - ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A - -// uint64_t tempaddr; - - /* Check for broadcast message */ - if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { - ETHBUF(raw_buf)->dest.addr[0] = 0x33; - ETHBUF(raw_buf)->dest.addr[1] = 0x33; - ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; - ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; - ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; - ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; - } else { - /* Otherwise we have a real address */ -// tempaddr = p->dest_addr.addr64; -// byte_reverse((uint8_t *)&tempaddr, 8); - mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]), - (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); - } - -// tempaddr = p->src_addr.addr64; -// memcpy(&tempaddr,packetbuf_addr(PACKETBUF_ADDR_SENDER),sizeof(tempaddr)); -// byte_reverse((uint8_t *)&tempaddr, 8); - mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr); - -// printf("Low2Eth: Sending 802.15.4 packet to ethernet\n\r"); - - sendlen += UIP_LLH_LEN; - usb_eth_send(raw_buf, sendlen, 0); -// rndis_stat.rxok++; +#ifdef RF230BB_HOOK_TX_PACKET +#if !RF230_CONF_CHECKSUM + { // Add a checksum before we log the packet out + uint16_t checksum; + checksum = crc16_data(payload, payload_len, 0); + memcpy(buffer+total_len-CHECKSUM_LEN,&checksum,CHECKSUM_LEN); } -#endif /* JACKDAW */ +#endif /* RF230_CONF_CHECKSUM */ + RF230BB_HOOK_TX_PACKET(buffer,total_len); +#endif + +bail: RELEASE_LOCK(); - return 0; + return ret; } /*---------------------------------------------------------------------------*/ static int rf230_send(const void *payload, unsigned short payload_len) { - rf230_prepare(payload, payload_len); -#if JACKDAW -// In sniffer mode we don't ever send anything - if (usbstick_mode.sendToRf == 0) { - uip_len = 0; - return 0; - } -#endif /* JACKDAW */ - return rf230_transmit(payload_len); + int ret = 0; + +#ifdef RF230BB_HOOK_IS_SEND_ENABLED + if(!RF230BB_HOOK_IS_SEND_ENABLED()) { + goto bail; + } +#endif + + if((ret=rf230_prepare(payload, payload_len))) { +#if DEBUG + printf_P(PSTR("rf230_send: Unable to send, prep failed (%d)\n"),ret); +#endif + goto bail; + } + + ret = rf230_transmit(payload_len); + +bail: + return ret; } /*---------------------------------------------------------------------------*/ int @@ -862,7 +849,7 @@ rf230_on(void) return 1; } /*---------------------------------------------------------------------------*/ -int +uint8_t rf230_get_channel(void) { //jackdaw reads zero channel, raven reads correct channel? @@ -871,7 +858,7 @@ rf230_get_channel(void) } /*---------------------------------------------------------------------------*/ void -rf230_set_channel(int c) +rf230_set_channel(uint8_t c) { /* Wait for any transmission to end. */ // PRINTF("rf230: Set Channel %u\n",c); @@ -883,7 +870,7 @@ rf230_set_channel(int c) void rf230_set_pan_addr(unsigned pan, unsigned addr, - const uint8_t *ieee_addr) + const uint8_t ieee_addr[8]) //rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr) { PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr); @@ -1083,19 +1070,19 @@ if (RF230_receive_on) { } /* Transfer the frame, stripping the footer */ framep=&(rxframe.data[0]); - memcpy(buf,framep,len-AUX_LEN); + memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN); framep+=len-AUX_LEN; /* Clear the length field to allow buffering of the next packet */ rxframe.length=0; #if RF230_CONF_CHECKSUM memcpy(&checksum,framep,CHECKSUM_LEN); - framep+=CHECKSUM_LEN; #endif /* RF230_CONF_CHECKSUM */ + framep+=CHECKSUM_LEN; #if RF230_CONF_TIMESTAMPS memcpy(&t,framep,TIMESTAMP_LEN); - framep+=TIMESTAMP_LEN; #endif /* RF230_CONF_TIMESTAMPS */ + framep+=TIMESTAMP_LEN; #if FOOTER_LEN memcpy(footer,framep,FOOTER_LEN); #endif @@ -1152,52 +1139,11 @@ if (RF230_receive_on) { // } // RELEASE_LOCK(); - if(len < AUX_LEN) { - return 0; - } -#if JACKDAW -/*------------------------------------------------------------*/ -/* If jackdaw report frame to ethernet interface */ -// mac_logRXtoEthernet(¶ms, &result); - if (usbstick_mode.raw != 0) { - uint8_t sendlen; - /* Get the raw frame */ - memcpy(&raw_buf[UIP_LLH_LEN], buf, len); - sendlen = len; +#ifdef RF230BB_HOOK_RX_PACKET + RF230BB_HOOK_RX_PACKET(buf,len); +#endif - /* Setup generic ethernet stuff */ - ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A - -// uint64_t tempaddr; - - /* Check for broadcast message */ - if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { - ETHBUF(raw_buf)->dest.addr[0] = 0x33; - ETHBUF(raw_buf)->dest.addr[1] = 0x33; - ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; - ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; - ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; - ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; - } else { - /* Otherwise we have a real address */ -// tempaddr = p->dest_addr.addr64; -// byte_reverse((uint8_t *)&tempaddr, 8); - mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]), - (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); - } - -// tempaddr = p->src_addr.addr64; -// memcpy(&tempaddr,packetbuf_addr(PACKETBUF_ADDR_SENDER),sizeof(tempaddr)); -// byte_reverse((uint8_t *)&tempaddr, 8); - mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr); - -// printf("Low2Eth: Sending 802.15.4 packet to ethernet\n\r"); - - sendlen += UIP_LLH_LEN; - usb_eth_send(raw_buf, sendlen, 0); - } -#endif /* JACKDAW */ return len - AUX_LEN; @@ -1217,30 +1163,23 @@ rf230_set_txpower(uint8_t power) RELEASE_LOCK(); } /*---------------------------------------------------------------------------*/ -int +uint8_t rf230_get_txpower(void) { - uint8_t power; - if (radio_is_sleeping() ==true) { - PRINTF("rf230_get_txpower:Sleeping"); - return 0; - } else { -// return hal_subregister_read(SR_TX_PWR); - power=hal_subregister_read(SR_TX_PWR); - if (power==0) { - PRINTSHORT("PZ"); - return 1; - } else { - return power; - } - } + uint8_t power = TX_PWR_UNDEFINED; + if (radio_is_sleeping()) { + PRINTF("rf230_get_txpower:Sleeping"); + } else { + power = hal_subregister_read(SR_TX_PWR); + } + return power; } /*---------------------------------------------------------------------------*/ -int -rf230_rssi(void) +uint8_t +rf230_get_raw_rssi(void) { - int rssi; - int radio_was_off = 0; + uint8_t rssi; + bool radio_was_off = 0; /*The RSSI measurement should only be done in RX_ON or BUSY_RX.*/ if(!RF230_receive_on) { @@ -1249,11 +1188,6 @@ rf230_rssi(void) } rssi = (int)((signed char)hal_subregister_read(SR_RSSI)); - if (rssi==0) { - DEBUGFLOW('r'); - PRINTF("RSZ"); - rssi=1; - } if(radio_was_off) { rf230_off(); diff --git a/cpu/avr/radio/rf230bb/rf230bb.h b/cpu/avr/radio/rf230bb/rf230bb.h index 6a2f0e515..1e2d0f96b 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.h +++ b/cpu/avr/radio/rf230bb/rf230bb.h @@ -45,7 +45,7 @@ * \file * \brief This file contains radio driver code. * - * $Id: rf230bb.h,v 1.2 2010/02/22 22:23:18 dak664 Exp $ + * $Id: rf230bb.h,v 1.3 2010/09/17 21:59:09 dak664 Exp $ */ #ifndef RADIO_H @@ -73,6 +73,11 @@ #define TX_PWR_3DBM ( 0 ) #define TX_PWR_17_2DBM ( 15 ) +#define TX_PWR_MAX TX_PWR_3DBM +#define TX_PWR_MIN TX_PWR_17_2DBM +#define TX_PWR_UNDEFINED (TX_PWR_MIN+1) + + #define BATTERY_MONITOR_HIGHEST_VOLTAGE ( 15 ) #define BATTERY_MONITOR_VOLTAGE_UNDER_THRESHOLD ( 0 ) #define BATTERY_MONITOR_HIGH_VOLTAGE ( 1 ) @@ -168,89 +173,44 @@ typedef enum{ }radio_clkm_speed_t; typedef void (*radio_rx_callback) (uint16_t data); -extern uint8_t rxMode; + + +/* Hook Documentation +** +** Sniffing Hooks: +** RF230BB_HOOK_TX_PACKET(buffer,total_len) +** RF230BB_HOOK_RX_PACKET(buf,len) +** +** RF230BB_HOOK_IS_SEND_ENABLED() +** RF230BB_HOOK_RADIO_ON() +** RF230BB_HOOK_RADIO_OFF() +** +*/ + + /*============================ PROTOTYPES ====================================*/ + const struct radio_driver rf230_driver; + int rf230_init(void); //int rf230_on(void); //int rf230_off(void); -void rf230_set_channel(int channel); -int rf230_get_channel(void); -void rf230_set_pan_addr(unsigned pan,unsigned addr,const uint8_t *ieee_addr); -//void rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr); -//void rf230_set_txpower(uint8_t power); -int rf230_get_txpower(void); +void rf230_set_channel(uint8_t channel); +uint8_t rf230_get_channel(void); +void rf230_set_pan_addr(unsigned pan,unsigned addr,const uint8_t ieee_addr[8]); +void rf230_set_txpower(uint8_t power); +uint8_t rf230_get_txpower(void); -//extern signed char rf230_last_rssi; -//extern uint8_t rf230_last_correlation; +void rf230_set_promiscuous_mode(bool isPromiscuous); +bool rf230_is_ready_to_send(); -//int rf230_rssi(void); +extern signed char rf230_last_rssi; +extern uint8_t rf230_last_correlation; +uint8_t rf230_get_raw_rssi(void); +#define rf230_rssi rf230_get_raw_rssi -//#define CC2420_TXPOWER_MAX 31 -//#define CC2420_TXPOWER_MIN 0 - -/** - * Interrupt function, called from the simple-cc2420-arch driver. - * - */ -//int cc2420_interrupt(void); - -/* XXX hack: these will be made as Chameleon packet attributes */ -//extern rtimer_clock_t rf230_time_of_arrival,rf230_time_of_departure; -//extern int rf230_authority_level_of_sender; - - -//radio_status_t radio_init(bool cal_rc_osc, -// hal_rx_start_isr_event_handler_t rx_event, -// hal_trx_end_isr_event_handler_t trx_end_event, -// radio_rx_callback rx_callback); -//uint8_t radio_get_saved_rssi_value(void); -//uint8_t radio_get_operating_channel( void ); -//radio_status_t radio_set_operating_channel( uint8_t channel ); -//uint8_t radio_get_tx_power_level( void ); -//radio_status_t radio_set_tx_power_level( uint8_t power_level ); - -//uint8_t radio_get_cca_mode( void ); -//uint8_t radio_get_ed_threshold( void ); -//radio_status_t radio_set_cca_mode( uint8_t mode, uint8_t ed_threshold ); -//radio_status_t radio_do_cca( void ); -//radio_status_t radio_get_rssi_value( uint8_t *rssi ); - -//uint8_t radio_batmon_get_voltage_threshold( void ); -//uint8_t radio_batmon_get_voltage_range( void ); -//radio_status_t radio_batmon_configure( bool range, uint8_t voltage_threshold ); -//radio_status_t radio_batmon_get_status( void ); - -//uint8_t radio_get_clock_speed( void ); -//radio_status_t radio_set_clock_speed( bool direct, uint8_t clock_speed ); -//radio_status_t radio_calibrate_filter( void ); -//radio_status_t radio_calibrate_pll( void ); - -//uint8_t radio_get_trx_state( void ); -//radio_status_t radio_set_trx_state( uint8_t new_state ); -//radio_status_t radio_enter_sleep_mode( void ); -//radio_status_t radio_leave_sleep_mode( void ); -//void radio_reset_state_machine( void ); -//void radio_reset_trx( void ); - -//void radio_use_auto_tx_crc( bool auto_crc_on ); -//radio_status_t radio_send_data( uint8_t data_length, uint8_t *data ); - -//uint8_t radio_get_device_role( void ); -//void radio_set_device_role( bool i_am_coordinator ); -//uint16_t radio_get_pan_id( void ); -//void radio_set_pan_id( uint16_t new_pan_id ); -//uint16_t radio_get_short_address( void ); -//void radio_set_short_address( uint16_t new_short_address ); -//void radio_get_extended_address( uint8_t *extended_address ); -//void radio_set_extended_address( uint8_t *extended_address ); -//radio_status_t radio_configure_csma( uint8_t seed0, uint8_t be_csma_seed1 ); -//bool calibrate_rc_osc_clkm(void); -//void calibrate_rc_osc_32k(void); -//uint8_t * radio_frame_data(void); -//uint8_t radio_frame_length(void); #define delay_us( us ) ( _delay_loop_2( ( F_CPU / 4000000UL ) * ( us ) ) ) #endif diff --git a/cpu/avr/settings.c b/cpu/avr/settings.c new file mode 100644 index 000000000..5c9b255ce --- /dev/null +++ b/cpu/avr/settings.c @@ -0,0 +1,275 @@ + +#include +//#include +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#include +#include "settings.h" +#include "dev/eeprom.h" +#include +#include +#include +#include +#include "contiki.h" + +#ifndef SETTINGS_TOP_ADDR +#define SETTINGS_TOP_ADDR (E2END-4) //!< Defaults to end of EEPROM, minus 4 bytes for avrdude erase count +#endif + +#ifndef SETTINGS_MAX_SIZE +#define SETTINGS_MAX_SIZE (1024) //!< Defaults to 1KB +#endif + +//#pragma mark - +//#pragma mark Private Functions + +typedef struct { + uint8_t size_extra; + uint8_t size_low; + uint8_t size_check; + settings_key_t key; +} item_header_t; + +inline static bool +settings_is_item_valid_(eeprom_addr_t item_addr) { + item_header_t header = {}; + + if(item_addr==EEPROM_NULL) + return false; + +// if((SETTINGS_TOP_ADDR-item_addr)>=SETTINGS_MAX_SIZE-3) +// return false; + + eeprom_read( + item_addr+1-sizeof(header), + (unsigned char*)&header, + sizeof(header) + ); + + if((uint8_t)header.size_check!=(uint8_t)~header.size_low) + return false; + + // TODO: Check length as well + + return true; +} + +inline static settings_key_t +settings_get_key_(eeprom_addr_t item_addr) { + item_header_t header; + + eeprom_read( + item_addr+1-sizeof(header), + (unsigned char*)&header, + sizeof(header) + ); + + if((uint8_t)header.size_check!=(uint8_t)~header.size_low) + return SETTINGS_INVALID_KEY; + + return header.key; +} + +inline static size_t +settings_get_value_length_(eeprom_addr_t item_addr) { + item_header_t header; + size_t ret = 0; + + eeprom_read( + item_addr+1-sizeof(header), + (unsigned char*)&header, + sizeof(header) + ); + + if((uint8_t)header.size_check!=(uint8_t)~header.size_low) + goto bail; + + ret = header.size_low; + + if(ret&(1<<7)) { + ret = ((ret&~(1<<7))<<8) | header.size_extra; + } + +bail: + return ret; +} + +inline static eeprom_addr_t +settings_get_value_addr_(eeprom_addr_t item_addr) { + size_t len = settings_get_value_length_(item_addr); + + if(len>128) + return item_addr+1-sizeof(item_header_t)-len; + + return item_addr+1-sizeof(item_header_t)+1-len; +} + +inline static eeprom_addr_t +settings_next_item_(eeprom_addr_t item_addr) { + return settings_get_value_addr_(item_addr)-1; +} + + +//#pragma mark - +//#pragma mark Public Functions + +bool +settings_check(settings_key_t key,uint8_t index) { + bool ret = false; + eeprom_addr_t current_item = SETTINGS_TOP_ADDR; + + for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) { + if(settings_get_key_(current_item)==key) { + if(!index) { + ret = true; + break; + } else { + // Nope, keep looking + index--; + } + } + } + + return ret; +} + +settings_status_t +settings_get(settings_key_t key,uint8_t index,unsigned char* value,size_t* value_size) { + settings_status_t ret = SETTINGS_STATUS_NOT_FOUND; + eeprom_addr_t current_item = SETTINGS_TOP_ADDR; + + for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) { + if(settings_get_key_(current_item)==key) { + if(!index) { + // We found it! + *value_size = MIN(*value_size,settings_get_value_length_(current_item)); + eeprom_read( + settings_get_value_addr_(current_item), + value, + *value_size + ); + ret = SETTINGS_STATUS_OK; + break; + } else { + // Nope, keep looking + index--; + } + } + } + + return ret; +} + +settings_status_t +settings_add(settings_key_t key,const unsigned char* value,size_t value_size) { + settings_status_t ret = SETTINGS_STATUS_FAILURE; + eeprom_addr_t current_item = SETTINGS_TOP_ADDR; + item_header_t header; + + // Find end of list + for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)); + + if(current_item==EEPROM_NULL) + goto bail; + + // TODO: size check! + + header.key = key; + + if(value_size<0x80) { + // If the value size is less than 128, then + // we can get away with only using one byte + // as the size. + header.size_low = value_size; + } else if(value_size<=SETTINGS_MAX_VALUE_SIZE) { + // If the value size of larger than 128, + // then we need to use two bytes. Store + // the most significant 7 bits in the first + // size byte (with MSB set) and store the + // least significant bits in the second + // byte (with LSB clear) + header.size_low = (value_size>>7) | 0x80; + header.size_extra = value_size & ~0x80; + } else { + // Value size way too big! + goto bail; + } + + header.size_check = ~header.size_low; + + // Write the header first + eeprom_write( + current_item+1-sizeof(header), + (unsigned char*)&header, + sizeof(header) + ); + + // Sanity check, remove once confident + if(settings_get_value_length_(current_item)!=value_size) { + goto bail; + } + + // Now write the data + eeprom_write( + settings_get_value_addr_(current_item), + (unsigned char*)value, + value_size + ); + + ret = SETTINGS_STATUS_OK; + +bail: + return ret; +} + +settings_status_t +settings_set(settings_key_t key,const unsigned char* value,size_t value_size) { + settings_status_t ret = SETTINGS_STATUS_FAILURE; + eeprom_addr_t current_item = SETTINGS_TOP_ADDR; + + for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) { + if(settings_get_key_(current_item)==key) { + break; + } + } + + if((current_item==EEPROM_NULL) || !settings_is_item_valid_(current_item)) { + ret = settings_add(key,value,value_size); + goto bail; + } + + if(value_size!=settings_get_value_length_(current_item)) { + // Requires the settings store to be shifted. Currently unimplemented. + goto bail; + } + + // Now write the data + eeprom_write( + settings_get_value_addr_(current_item), + (unsigned char*)value, + value_size + ); + + ret = SETTINGS_STATUS_OK; + +bail: + return ret; +} + +settings_status_t +settings_delete(settings_key_t key,uint8_t index) { + // Requires the settings store to be shifted. Currently unimplemented. + // TODO: Writeme! + return SETTINGS_STATUS_UNIMPLEMENTED; +} + + +void +settings_wipe(void) { + size_t i = SETTINGS_TOP_ADDR-SETTINGS_MAX_SIZE; + for(;i<=SETTINGS_TOP_ADDR;i++) { + eeprom_write_byte((uint8_t*)i,0xFF); + wdt_reset(); + } +} + + diff --git a/cpu/avr/settings.h b/cpu/avr/settings.h new file mode 100644 index 000000000..be3c4a2c3 --- /dev/null +++ b/cpu/avr/settings.h @@ -0,0 +1,118 @@ +#ifndef __AVR_SETTINGS_H__ +#define __AVR_SETTINGS_H__ + +#include +#include +#include + +typedef uint16_t settings_key_t; + +#define SETTINGS_KEY_EUI64 'E8' //!< Value always 8 bytes long +#define SETTINGS_KEY_EUI48 'E6' //!< Value always 6 bytes long +#define SETTINGS_KEY_CHANNEL 'CH' //!< Value always 1 byte long +#define SETTINGS_KEY_TXPOWER 'TP' //!< Value always 1 byte long +#define SETTINGS_KEY_PAN_ID 'PN' //!< Value always 2 bytes long +#define SETTINGS_KEY_PAN_ADDR 'PA' //!< Value always 2 bytes long +#define SETTINGS_KEY_AES128KEY 'SK' //!< Value always 16 bytes long +#define SETTINGS_KEY_AES128ENABLED 'SE' //!< Value always 16 bytes long + +typedef enum { + SETTINGS_STATUS_OK=0, + SETTINGS_STATUS_INVALID_ARGUMENT, + SETTINGS_STATUS_NOT_FOUND, + SETTINGS_STATUS_OUT_OF_SPACE, + SETTINGS_STATUS_UNIMPLEMENTED, + SETTINGS_STATUS_FAILURE, +} settings_status_t; + +// Use this when you want to retrieve the last item +#define SETTINGS_LAST_INDEX (0xFF) + +#define SETTINGS_INVALID_KEY (0x00) + +#define SETTINGS_MAX_VALUE_SIZE (0x3FFF) // 16383 bytes + +extern settings_status_t settings_get(settings_key_t key,uint8_t index,unsigned char* value,size_t* value_size); +extern settings_status_t settings_add(settings_key_t key,const unsigned char* value,size_t value_size); +extern bool settings_check(settings_key_t key,uint8_t index); +extern void settings_wipe(void); + +extern settings_status_t settings_set(settings_key_t key,const unsigned char* value,size_t value_size); +extern settings_status_t settings_delete(settings_key_t key,uint8_t index); + +//#pragma mark - +//#pragma mark Inline convenience functions + +static inline uint8_t +settings_get_uint8(settings_key_t key,uint8_t index) { + uint8_t ret = 0; + size_t sizeof_uint8 = sizeof(uint8_t); + settings_get(key,index,(unsigned char*)&ret,&sizeof_uint8); + return ret; +} + +static inline settings_status_t +settings_add_uint8(settings_key_t key,uint8_t value) { + return settings_add(key,(const unsigned char*)&value,sizeof(uint8_t)); +} + +static inline settings_status_t +settings_set_uint8(settings_key_t key,uint8_t value) { + return settings_set(key,(const unsigned char*)&value,sizeof(uint8_t)); +} + +static inline uint16_t +settings_get_uint16(settings_key_t key,uint8_t index) { + uint16_t ret = 0; + size_t sizeof_uint16 = sizeof(uint16_t); + settings_get(key,index,(unsigned char*)&ret,&sizeof_uint16); + return ret; +} + +static inline settings_status_t +settings_add_uint16(settings_key_t key,uint16_t value) { + return settings_add(key,(const unsigned char*)&value,sizeof(uint16_t)); +} + +static inline settings_status_t +settings_set_uint16(settings_key_t key,uint16_t value) { + return settings_set(key,(const unsigned char*)&value,sizeof(uint16_t)); +} + +static inline uint32_t +settings_get_uint32(settings_key_t key,uint8_t index) { + uint32_t ret = 0; + size_t sizeof_uint32 = sizeof(uint32_t); + settings_get(key,index,(unsigned char*)&ret,&sizeof_uint32); + return ret; +} + +static inline settings_status_t +settings_add_uint32(settings_key_t key,uint32_t value) { + return settings_add(key,(const unsigned char*)&value,sizeof(uint32_t)); +} + +static inline settings_status_t +settings_set_uint32(settings_key_t key,uint32_t value) { + return settings_set(key,(const unsigned char*)&value,sizeof(uint32_t)); +} + +static inline uint64_t +settings_get_uint64(settings_key_t key,uint8_t index) { + uint64_t ret = 0; + size_t sizeof_uint64 = sizeof(uint64_t); + settings_get(key,index,(unsigned char*)&ret,&sizeof_uint64); + return ret; +} + +static inline settings_status_t +settings_add_uint64(settings_key_t key,uint64_t value) { + return settings_add(key,(const unsigned char*)&value,sizeof(uint64_t)); +} + +static inline settings_status_t +settings_set_uint64(settings_key_t key,uint64_t value) { + return settings_set(key,(const unsigned char*)&value,sizeof(uint64_t)); +} + +#endif diff --git a/cpu/avr/watchdog.c b/cpu/avr/watchdog.c index 23c9b2c22..d27c89c5d 100644 --- a/cpu/avr/watchdog.c +++ b/cpu/avr/watchdog.c @@ -28,35 +28,52 @@ * * This file is part of the Contiki operating system. * - * @(#)$Id: watchdog.c,v 1.1 2010/02/07 07:43:35 adamdunkels Exp $ + * @(#)$Id: watchdog.c,v 1.2 2010/09/17 21:59:09 dak664 Exp $ */ /* Dummy watchdog routines for the Raven 1284p */ #include "dev/watchdog.h" +#include +#include + +static int stopped = 0; /*---------------------------------------------------------------------------*/ void watchdog_init(void) { + MCUSR&=~(1< + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +/** + \ingroup usbstick + \defgroup cdctask CDC Task + @{ + */ + +//_____ I N C L U D E S ___________________________________________________ + + +#include "contiki.h" +#include "usb_drv.h" +#include "usb_descriptors.h" +#include "usb_specific_request.h" +#include "cdc_task.h" +#include "serial/uart_usb_lib.h" +#include "rndis/rndis_protocol.h" +#include "rndis/rndis_task.h" +#include "sicslow_ethernet.h" +#if RF230BB +#include "rf230bb.h" +#else +#include "radio.h" +#endif +#include +#include +#include "dev/watchdog.h" +#include "rng.h" + +#include "bootloader.h" + +#include +#include +#include +#include + +#if JACKDAW_CONF_USE_SETTINGS +#include "settings.h" +#endif + +#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) +#define PRINTF printf +#define PRINTF_P printf_P + +//_____ M A C R O S ________________________________________________________ + + +#define bzero(ptr,size) memset(ptr,0,size) + +//_____ D E F I N I T I O N S ______________________________________________ + + +#define IAD_TIMEOUT_DETACH 300 +#define IAD_TIMEOUT_ATTACH 600 + +//_____ D E C L A R A T I O N S ____________________________________________ + + +void menu_print(void); +void menu_process(char c); + +extern char usb_busy; + +//! Counter for USB Serial port +extern U8 tx_counter; + +//! Timers for LEDs +uint8_t led3_timer; + + +//! previous configuration +static uint8_t previous_uart_usb_control_line_state = 0; + + +static uint8_t timer = 0; +static struct etimer et; + + +PROCESS(cdc_process, "CDC serial process"); + +/** + * \brief Communication Data Class (CDC) Process + * + * This is the link between USB and the "good stuff". In this routine data + * is received and processed by CDC-ACM Class + */ +PROCESS_THREAD(cdc_process, ev, data_proc) +{ + PROCESS_BEGIN(); + + while(1) { + // turn off LED's if necessary + if (led3_timer) led3_timer--; + else Led3_off(); + + + if(Is_device_enumerated()) { + // If the configuration is different than the last time we checked... + if((uart_usb_get_control_line_state()&1)!=previous_uart_usb_control_line_state) { + previous_uart_usb_control_line_state = uart_usb_get_control_line_state()&1; + static FILE* previous_stdout; + + if(previous_uart_usb_control_line_state&1) { + previous_stdout = stdout; + uart_usb_init(); + uart_usb_set_stdout(); + menu_print(); + } else { + stdout = previous_stdout; + } + } + + //Flush buffer if timeout + if(timer >= 4 && tx_counter!=0 ){ + timer = 0; + uart_usb_flush(); + } else { + timer++; + } + + while (uart_usb_test_hit()){ + menu_process(uart_usb_getchar()); // See what they want + } + + + }//if (Is_device_enumerated()) + + + if (USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) { + etimer_set(&et, CLOCK_SECOND/80); + } else { + etimer_set(&et, CLOCK_SECOND); + } + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + } // while(1) + + PROCESS_END(); +} + +/** + \brief Print debug menu + */ +void menu_print(void) +{ + PRINTF_P(PSTR("\n\r********** Jackdaw Menu ******************\n\r")); + PRINTF_P(PSTR("* *\n\r")); + PRINTF_P(PSTR("* Main Menu: *\n\r")); + PRINTF_P(PSTR("* h,? Print this menu *\n\r")); + PRINTF_P(PSTR("* m Print current mode *\n\r")); + PRINTF_P(PSTR("* s Set to sniffer mode *\n\r")); + PRINTF_P(PSTR("* n Set to network mode *\n\r")); + PRINTF_P(PSTR("* c Set RF channel *\n\r")); + PRINTF_P(PSTR("* 6 Toggle 6lowpan *\n\r")); + PRINTF_P(PSTR("* r Toggle raw mode *\n\r")); + PRINTF_P(PSTR("* e Energy Scan *\n\r")); +#if USB_CONF_STORAGE + PRINTF_P(PSTR("* u Switch to mass-storage*\n\r")); +#endif + if(bootloader_is_present()) + PRINTF_P(PSTR("* D Switch to DFU mode *\n\r")); + PRINTF_P(PSTR("* R Reset (via WDT) *\n\r")); + PRINTF_P(PSTR("* *\n\r")); + PRINTF_P(PSTR("* Make selection at any time by pressing *\n\r")); + PRINTF_P(PSTR("* your choice on keyboard. *\n\r")); + PRINTF_P(PSTR("******************************************\n\r")); + PRINTF_P(PSTR("[Built "__DATE__"]\n\r")); +} + + +/** + \brief Process incomming char on debug port + */ +void menu_process(char c) +{ + + static enum menustate_enum /* Defines an enumeration type */ + { + normal, + channel + } menustate = normal; + + static char channel_string[3]; + static uint8_t channel_string_i = 0; + + int tempchannel; + + if (menustate == channel) { + + switch(c) { + case '\r': + case '\n': + + if (channel_string_i) { + channel_string[channel_string_i] = 0; + tempchannel = atoi(channel_string); + +#if RF230BB + if ((tempchannel < 11) || (tempchannel > 26)) { + PRINTF_P(PSTR("\n\rInvalid input\n\r")); + } else { + rf230_set_channel(tempchannel); +#else + if(radio_set_operating_channel(tempchannel)!=RADIO_SUCCESS) { + PRINTF_P(PSTR("\n\rInvalid input\n\r")); + } else { +#endif +#if JACKDAW_CONF_USE_SETTINGS + if(settings_set_uint8(SETTINGS_KEY_CHANNEL, tempchannel)!=SETTINGS_STATUS_OK) { + PRINTF_P(PSTR("\n\rChannel changed to %d, but unable to store in EEPROM!\n\r"),tempchannel); + } else +#else + AVR_ENTER_CRITICAL_REGION(); + eeprom_write_byte((uint8_t *) 9, tempchannel); //Write channel + eeprom_write_byte((uint8_t *)10, ~tempchannel); //Bit inverse as check + AVR_LEAVE_CRITICAL_REGION(); +#endif + PRINTF_P(PSTR("\n\rChannel changed to %d and stored in EEPROM.\n\r"),tempchannel); + } + } else { + PRINTF_P(PSTR("\n\rChannel unchanged.\n\r")); + } + + menustate = normal; + break; + + case '\b': + + if (channel_string_i) { + channel_string_i--; + PRINTF_P(PSTR("\b \b")); + } + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (channel_string_i > 1) { + // This time the user has gone too far. + // Beep at them. + putc('\a', stdout); + //uart_usb_putchar('\a'); + break; + } + putc(c, stdout); + //uart_usb_putchar(c); + + channel_string[channel_string_i] = c; + channel_string_i++; + break; + + default: + break; + } + + + } else { + + uint8_t i; + switch(c) { + case '\r': + case '\n': + break; + + case 'h': + case '?': + menu_print(); + break; + case '-': + PRINTF_P(PSTR("Bringing interface down\n\r")); + usb_eth_set_active(0); + break; + case '=': + case '+': + PRINTF_P(PSTR("Bringing interface up\n\r")); + usb_eth_set_active(1); + break; + + case 't': + // I added this to test my "strong" random number generator. + PRINTF_P(PSTR("RNG Output: ")); + { + uint8_t value = rng_get_uint8(); + uint8_t i; + for(i=0;i<8;i++) { + uart_usb_putchar(((value>>(7-i))&1)?'1':'0'); + } + PRINTF_P(PSTR("\n\r")); + uart_usb_flush(); + watchdog_periodic(); + } + break; + + case 's': + PRINTF_P(PSTR("Jackdaw now in sniffer mode\n\r")); + usbstick_mode.sendToRf = 0; + usbstick_mode.translate = 0; + break; + + case 'n': + PRINTF_P(PSTR("Jackdaw now in network mode\n\r")); + usbstick_mode.sendToRf = 1; + usbstick_mode.translate = 1; + break; + + case '6': + if (usbstick_mode.sicslowpan) { + PRINTF_P(PSTR("Jackdaw does not perform 6lowpan translation\n\r")); + usbstick_mode.sicslowpan = 0; + } else { + PRINTF_P(PSTR("Jackdaw now performs 6lowpan translations\n\r")); + usbstick_mode.sicslowpan = 1; + } + + break; + + case 'r': + if (usbstick_mode.raw) { + PRINTF_P(PSTR("Jackdaw does not capture raw frames\n\r")); + usbstick_mode.raw = 0; + } else { + PRINTF_P(PSTR("Jackdaw now captures raw frames\n\r")); + usbstick_mode.raw = 1; + } + break; + + case 'c': +#if RF230BB + PRINTF_P(PSTR("Select 802.15.4 Channel in range 11-26 [%d]: "), rf230_get_channel()); +#else + PRINTF_P(PSTR("Select 802.15.4 Channel in range 11-26 [%d]: "), radio_get_operating_channel()); +#endif + menustate = channel; + channel_string_i = 0; + break; + + + + case 'm': + PRINTF_P(PSTR("Currently Jackdaw:\n\r * Will ")); + if (usbstick_mode.sendToRf == 0) { PRINTF_P(PSTR("not "));} + PRINTF_P(PSTR("send data over RF\n\r * Will ")); + if (usbstick_mode.translate == 0) { PRINTF_P(PSTR("not "));} + PRINTF_P(PSTR("change link-local addresses inside IP messages\n\r * Will ")); + if (usbstick_mode.sicslowpan == 0) { PRINTF_P(PSTR("not "));} + PRINTF_P(PSTR("decompress 6lowpan headers\n\r * Will ")); + if (usbstick_mode.raw == 0) { PRINTF_P(PSTR("not "));} + PRINTF_P(PSTR("Output raw 802.15.4 frames\n\r")); + PRINTF_P(PSTR(" * USB Ethernet MAC: %02x:%02x:%02x:%02x:%02x:%02x\n"), + ((uint8_t *)&usb_ethernet_addr)[0], + ((uint8_t *)&usb_ethernet_addr)[1], + ((uint8_t *)&usb_ethernet_addr)[2], + ((uint8_t *)&usb_ethernet_addr)[3], + ((uint8_t *)&usb_ethernet_addr)[4], + ((uint8_t *)&usb_ethernet_addr)[5] + ); + extern uint64_t macLongAddr; + PRINTF_P(PSTR(" * 802.15.4 EUI-64: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"), + ((uint8_t *)&macLongAddr)[0], + ((uint8_t *)&macLongAddr)[1], + ((uint8_t *)&macLongAddr)[2], + ((uint8_t *)&macLongAddr)[3], + ((uint8_t *)&macLongAddr)[4], + ((uint8_t *)&macLongAddr)[5], + ((uint8_t *)&macLongAddr)[6], + ((uint8_t *)&macLongAddr)[7] + ); +#if RF230BB + PRINTF_P(PSTR(" * Operates on channel %d\n\r"), rf230_get_channel()); + PRINTF_P(PSTR(" * TX Power Level: 0x%02X\n\r"), rf230_get_txpower()); + PRINTF_P(PSTR(" * Current RSSI: %ddB\n\r"), -91+3*(rf230_rssi()-1)); + PRINTF_P(PSTR(" * Last RSSI: %ddB\n\r"), -91+3*(rf230_last_rssi-1)); +#else // RF230BB + PRINTF_P(PSTR(" * Operates on channel %d\n\r"), radio_get_operating_channel()); + PRINTF_P(PSTR(" * TX Power Level: 0x%02X\n\r"), radio_get_tx_power_level()); + { + PRINTF_P(PSTR(" * Current RSSI: ")); + int8_t rssi = 0; + if(radio_get_rssi_value(&rssi)==RADIO_SUCCESS) + PRINTF_P(PSTR("%ddB\n\r"), -91+3*(rssi-1)); + else + PRINTF_P(PSTR("Unknown\n\r")); + } + +#endif // !RF230BB + PRINTF_P(PSTR(" * Configuration: %d\n\r"), usb_configuration_nb); + PRINTF_P(PSTR(" * usb_eth_is_active: %d\n\r"), usb_eth_is_active); + break; + + case 'e': + PRINTF_P(PSTR("Energy Scan:\n")); + uart_usb_flush(); + { + uint8_t i; + uint16_t j; +#if RF230BB + uint8_t previous_channel = rf230_get_channel(); +#else // RF230BB + uint8_t previous_channel = radio_get_operating_channel(); +#endif + int8_t RSSI, maxRSSI[17]; + uint16_t accRSSI[17]; + + bzero((void*)accRSSI,sizeof(accRSSI)); + bzero((void*)maxRSSI,sizeof(maxRSSI)); + + for(j=0;j<(1<<12);j++) { + for(i=11;i<=26;i++) { +#if RF230BB + rf230_set_channel(i); +#else // RF230BB + radio_set_operating_channel(i); +#endif + _delay_us(3*10); +#if RF230BB + RSSI = rf230_rssi(); +#else // RF230BB + radio_get_rssi_value(&RSSI); +#endif + maxRSSI[i-11]=Max(maxRSSI[i-11],RSSI); + accRSSI[i-11]+=RSSI; + } + if(j&(1<<7)) { + Led3_on(); + if(!(j&((1<<7)-1))) { + PRINTF_P(PSTR(".")); + uart_usb_flush(); + } + } + else + Led3_off(); + watchdog_periodic(); + } +#if RF230BB + rf230_set_channel(previous_channel); +#else // RF230BB + radio_set_operating_channel(previous_channel); +#endif + PRINTF_P(PSTR("\n")); + for(i=11;i<=26;i++) { + uint8_t activity=Min(maxRSSI[i-11],accRSSI[i-11]/(1<<7)); + PRINTF_P(PSTR(" %d: %02ddB "),i, -91+3*(maxRSSI[i-11]-1)); + for(;activity--;maxRSSI[i-11]--) { + PRINTF_P(PSTR("#")); + } + for(;maxRSSI[i-11]>0;maxRSSI[i-11]--) { + PRINTF_P(PSTR(":")); + } + PRINTF_P(PSTR("\n")); + uart_usb_flush(); + } + + } + PRINTF_P(PSTR("Done.\n")); + uart_usb_flush(); + + break; + + + case 'D': + { + PRINTF_P(PSTR("Entering DFU Mode...\n\r")); + uart_usb_flush(); + Leds_on(); + for(i = 0; i < 10; i++)_delay_ms(100); + Leds_off(); + Jump_To_Bootloader(); + } + break; + case 'R': + { + PRINTF_P(PSTR("Resetting...\n\r")); + uart_usb_flush(); + Leds_on(); + for(i = 0; i < 10; i++)_delay_ms(100); + Usb_detach(); + for(i = 0; i < 20; i++)_delay_ms(100); + watchdog_reboot(); + } + break; + +#if USB_CONF_STORAGE + case 'u': + + //Mass storage mode + usb_mode = mass_storage; + + //No more serial port + stdout = NULL; + + //RNDIS is over + rndis_state = rndis_uninitialized; + Leds_off(); + + //Deatch USB + Usb_detach(); + + //Wait a few seconds + for(i = 0; i < 50; i++) + _delay_ms(100); + + //Attach USB + Usb_attach(); + + + break; +#endif + + default: + PRINTF_P(PSTR("%c is not a valid option! h for menu\n\r"), c); + break; + } + + + } + + return; + +} + + +/** + @brief This will enable the VCP_TRX_END LED for a period +*/ +void vcptx_end_led(void) +{ + Led3_on(); + led3_timer = 5; +} +/** @} */ + diff --git a/platform/avr-ravenusb/cdc_task.h b/platform/avr-ravenusb/cdc_task.h new file mode 100644 index 000000000..66042b49d --- /dev/null +++ b/platform/avr-ravenusb/cdc_task.h @@ -0,0 +1,74 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file cdc_task.h ************************************************************ + * + * \brief + * This file manages the CDC task for the virtual COM port. + * + * \addtogroup usbstick + * + * \author + * Colin O'Flynn + * + ******************************************************************************/ +/* Copyright (c) 2008 ATMEL Corporation + Copyright (c) 2008 Colin O'Flynn + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _CDC_TASK_H_ +#define _CDC_TASK_H_ + +/** + \addtogroup cdctask + @{ + */ + +//_____ I N C L U D E S ____________________________________________________ + + +#include "config.h" + +//_____ M A C R O S ________________________________________________________ + + + +//_____ D E C L A R A T I O N S ____________________________________________ + + +void sof_action(void); +void vcptx_end_led(void); + +void rawmode_enable(void); +void rawmode_disable(void); + +PROCESS_NAME(cdc_process); + +/** @} */ + +#endif /* _CDC_TASK_H_ */ + diff --git a/platform/avr-ravenusb/contiki-conf.h b/platform/avr-ravenusb/contiki-conf.h index 908ac9110..f5a29f5fc 100644 --- a/platform/avr-ravenusb/contiki-conf.h +++ b/platform/avr-ravenusb/contiki-conf.h @@ -43,6 +43,14 @@ #ifndef __CONTIKI_CONF_H__ #define __CONTIKI_CONF_H__ +#include +#include +#include + +/* ************************************************************************** */ +//#pragma mark Basic Configuration +/* ************************************************************************** */ + /* MCU and clock rate */ #define MCU_MHZ 8 #define PLATFORM PLATFORM_AVR @@ -51,6 +59,14 @@ /* Clock ticks per second */ #define CLOCK_CONF_SECOND 125 +/* Mac address, RF channel, PANID from EEPROM settings manager */ +/* Generate random MAC address on first startup */ +/* Random number from radio clock skew or ADC noise */ +#define JACKDAW_CONF_USE_SETTINGS 1 +#define JACKDAW_CONF_RANDOM_MAC 0 +#define RNG_CONF_USE_RADIO_CLOCK 1 +//#define RNG_CONF_USE_ADC 1 + /* Since clock_time_t is 16 bits, maximum interval is 524 seconds */ #define RIME_CONF_BROADCAST_ANNOUNCEMENT_MAX_TIME CLOCK_CONF_SECOND * 524UL /*Default uses 600*/ @@ -74,13 +90,71 @@ #define CCIF #define CLIF -#define RIMEADDR_CONF_SIZE 8 +/* ************************************************************************** */ +//#pragma mark USB Ethernet Hooks +/* ************************************************************************** */ -#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 -#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 +#ifndef USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET +#if RF230BB +#define USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET() rf230_is_ready_to_send() +#else +static inline uint8_t radio_is_ready_to_send_() { + switch(radio_get_trx_state()) { + case BUSY_TX: + case BUSY_TX_ARET: + return 0; + } + return 1; +} +#define USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET() radio_is_ready_to_send_() +#endif +#endif + +#ifndef USB_ETH_HOOK_HANDLE_INBOUND_PACKET +#define USB_ETH_HOOK_HANDLE_INBOUND_PACKET(buffer,len) do { uip_len = len ; mac_ethernetToLowpan(buffer); } while(0) +#endif + +#ifndef USB_ETH_HOOK_SET_PROMISCIOUS_MODE +#if RF230BB +#define USB_ETH_HOOK_SET_PROMISCIOUS_MODE(value) rf230_set_promiscuous_mode(value) +#else +#define USB_ETH_HOOK_SET_PROMISCIOUS_MODE(value) radio_set_trx_state(value?RX_ON:RX_AACK_ON) +#endif +#endif + +#ifndef USB_ETH_HOOK_INIT +#define USB_ETH_HOOK_INIT() mac_ethernetSetup() +#endif + +/* ************************************************************************** */ +//#pragma mark RF230BB Hooks +/* ************************************************************************** */ + +//#define RF230BB_HOOK_RADIO_OFF() Led1_off() +//#define RF230BB_HOOK_RADIO_ON() Led1_on() +#define RF230BB_HOOK_TX_PACKET(buffer,total_len) mac_log_802_15_4_tx(buffer,total_len) +#define RF230BB_HOOK_RX_PACKET(buffer,total_len) mac_log_802_15_4_rx(buffer,total_len) +#define RF230BB_HOOK_IS_SEND_ENABLED() mac_is_send_enabled() +extern bool mac_is_send_enabled(void); +extern void mac_log_802_15_4_tx(const uint8_t* buffer, size_t total_len); +extern void mac_log_802_15_4_rx(const uint8_t* buffer, size_t total_len); + + +/* ************************************************************************** */ +//#pragma mark USB CDC-ACM (UART) Hooks +/* ************************************************************************** */ + +#define USB_CDC_ACM_HOOK_TX_END(char) vcptx_end_led() +#define USB_CDC_ACM_HOOK_CLS_CHANGED(state) vcptx_end_led() +#define USB_CDC_ACM_HOOK_CONFIGURED() vcptx_end_led() + +/* ************************************************************************** */ +//#pragma mark UIP Settings +/* ************************************************************************** */ #define UIP_CONF_LL_802154 1 #define UIP_CONF_LLH_LEN 14 +#define UIP_CONF_BUFSIZE UIP_LINK_MTU + UIP_LLH_LEN + 4 // +4 for vlan on macosx #define UIP_CONF_MAX_CONNECTIONS 4 #define UIP_CONF_MAX_LISTENPORTS 4 @@ -104,15 +178,38 @@ #define UIP_CONF_TCP_SPLIT 1 #define UIP_CONF_STATISTICS 1 -/* Disable mass storage enumeration for more debug string space */ -//#define USB_CONF_STORAGE 1 -/* Use either USB CDC or RS232 for stdout (or neither) */ -//#define USB_CONF_CDC 1 -#define USB_CONF_RS232 1 +/* ************************************************************************** */ +//#pragma mark Serial Port Settings +/* ************************************************************************** */ + +/* Disable mass storage enumeration for more program space */ +/* TODO: Mass storage is currently broken */ +#define USB_CONF_STORAGE 0 +/* Use either USB CDC or RS232 for stdout (or neither) */ +/* TODO:CDC is currently broken on windows/linux, use RS232 */ +#define USB_CONF_CDC 1 +//#define USB_CONF_RS232 1 + +/* ************************************************************************** */ +//#pragma mark RIME Settings +/* ************************************************************************** */ + +#define RIMEADDR_CONF_SIZE 8 + +/* ************************************************************************** */ +//#pragma mark SICSLOWPAN Settings +/* ************************************************************************** */ + +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #ifdef RF230BB #define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 //for barebones driver, sicslowpan calls radio->read function +/* ************************************************************************** */ +//#pragma mark NETSTACK Settings +/* ************************************************************************** */ + #if 1 /* Network setup */ /* No radio cycling */ #define NETSTACK_CONF_NETWORK sicslowpan_driver @@ -158,12 +255,19 @@ #error Network configuration not specified! #endif /* Network setup */ -#if 0 /* RPL */ + +/* ************************************************************************** */ +//#pragma mark RPL Settings +/* ************************************************************************** */ + +#define UIP_CONF_IPV6_RPL 0 + +#if UIP_CONF_IPV6_RPL + /* Not completely working yet. Link local pings work but address prefixes do not get assigned */ /* RPL requires the uip stack. Change #CONTIKI_NO_NET=1 to UIP_CONF_IPV6=1 in the examples makefile, or include the needed source files in /plaftorm/avr-ravenusb/Makefile.avr-ravenusb */ -#define UIP_CONF_IPV6_RPL 1 #define UIP_CONF_ROUTER 1 #define RPL_CONF_STATS 0 #define PROCESS_CONF_NO_PROCESS_NAMES 0 @@ -212,11 +316,13 @@ or include the needed source files in /plaftorm/avr-ravenusb/Makefile.avr-ravenu #define UIP_CONF_PINGADDRCONF 0 #define UIP_CONF_LOGGING 0 #endif -#endif /* RPL */ - - +#endif /* UIP_CONF_IPV6_RPL */ #endif /* RF230BB */ +/* ************************************************************************** */ +//#pragma mark Other Settings +/* ************************************************************************** */ + /* Route-Under-MAC uses 16-bit short addresses */ #if UIP_CONF_USE_RUM #undef UIP_CONF_LL_802154 diff --git a/platform/avr-ravenusb/contiki-raven-default-init-lowlevel.c b/platform/avr-ravenusb/contiki-raven-default-init-lowlevel.c index 3050e03e3..293e493bf 100644 --- a/platform/avr-ravenusb/contiki-raven-default-init-lowlevel.c +++ b/platform/avr-ravenusb/contiki-raven-default-init-lowlevel.c @@ -39,6 +39,7 @@ #include "usb_descriptors.h" #include "usb_specific_request.h" #include +#include "bootloader.h" uint8_t checkForFinger(void); @@ -54,6 +55,8 @@ init_lowlevel(void) Leds_off(); if (checkForFinger()) { + if(bootloader_is_present()) + Jump_To_Bootloader(); #ifdef WINXPSP2 usb_mode = mass_storage; #else diff --git a/platform/avr-ravenusb/contiki-raven-default-init-net.c b/platform/avr-ravenusb/contiki-raven-default-init-net.c index dc04474e5..043d637d0 100644 --- a/platform/avr-ravenusb/contiki-raven-default-init-net.c +++ b/platform/avr-ravenusb/contiki-raven-default-init-net.c @@ -35,36 +35,64 @@ #include "contiki-raven.h" #if !RF230BB #include "zmac.h" -#else -extern uint64_t macLongAddr; #endif #include "sicslowpan.h" -extern uint64_t rndis_ethernet_addr; +#include "sicslow_ethernet.h" +#include "rndis/rndis_task.h" + +void byte_reverse(uint8_t * bytes, uint8_t num) +{ + uint8_t tempbyte; + + uint8_t i, j; + + i = 0; + j = num - 1; + + while(i < j) { + tempbyte = bytes[i]; + bytes[i] = bytes[j]; + bytes[j] = tempbyte; + + j--; + i++; + } + + return; +} void init_net(void) { + extern uint64_t macLongAddr; + uint64_t usb_ethernet_addr; + // Because all of the logic below is done using little-endian + // 64-bit integers, we need to reverse the byte order before + // we can continue; + byte_reverse((uint8_t*)&macLongAddr,8); - - - /* Set local bit, Clear translate bit, Clear Multicast bit */ - macLongAddr &= ~(0x0700000000000000ULL); - macLongAddr |= 0x0200000000000000ULL; - + /* Set local bit, Clear translate bit, Clear Multicast bit */ + macLongAddr &= ~(0x0700000000000000ULL); + macLongAddr |= 0x0200000000000000ULL; - /* Set the Ethernet address to the 15.4 MAC address */ - rndis_ethernet_addr = macLongAddr; - - /* Remove the middle two bytes... */ - rndis_ethernet_addr = (rndis_ethernet_addr & 0xffffffUL) | ((rndis_ethernet_addr & 0xffffff0000000000ULL) >> 16); + /* Set the Ethernet address to the 15.4 MAC address */ + usb_ethernet_addr = macLongAddr; - /* Change ieee802.15.4 address to correspond with what the ethernet's - IPv6 address will be. This will have ff:fe in the middle. */ - macLongAddr = (macLongAddr & 0xffffff0000ffffffULL) | (0x000000fffe000000ULL); + /* Remove the middle two bytes... */ + usb_ethernet_addr = (usb_ethernet_addr & 0xffffffUL) | ((usb_ethernet_addr & 0xffffff0000000000ULL) >> 16); + + /* Change ieee802.15.4 address to correspond with what the ethernet's + IPv6 address will be. This will have ff:fe in the middle. */ + macLongAddr = (macLongAddr & 0xffffff0000ffffffULL) | (0x000000fffe000000ULL); #if !RF230BB - ieee15_4ManagerAddress.set_long_addr(macLongAddr); + ieee15_4ManagerAddress.set_long_addr(macLongAddr); #endif + + byte_reverse((uint8_t*)&macLongAddr,8); + byte_reverse((uint8_t*)&usb_ethernet_addr,6); + + usb_eth_set_mac_address((uint8_t*)&usb_ethernet_addr); } diff --git a/platform/avr-ravenusb/contiki-raven-main.c b/platform/avr-ravenusb/contiki-raven-main.c index 33811a5d6..5cce89a37 100644 --- a/platform/avr-ravenusb/contiki-raven-main.c +++ b/platform/avr-ravenusb/contiki-raven-main.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,7 @@ #include "usb_task.h" #if USB_CONF_CDC -#include "serial/cdc_task.h" +#include "cdc_task.h" #elif USB_CONF_RS232 #include "dev/rs232.h" #endif @@ -78,13 +79,21 @@ #include "storage/storage_task.h" #endif +#include "dev/watchdog.h" +#include "dev/usb/usb_drv.h" + +#if JACKDAW_CONF_USE_SETTINGS +#include "settings.h" +#endif + #if RF230BB //radio driver using contiki core mac #include "radio/rf230bb/rf230bb.h" #include "net/mac/frame802154.h" #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) extern int rf230_interrupt_flag; extern uint8_t rf230processflag; -rimeaddr_t addr,macLongAddr; +rimeaddr_t macLongAddr; +#define tmp_addr macLongAddr #else //legacy radio driver using Atmel/Cisco 802.15.4'ish MAC #include #include "mac.h" @@ -194,20 +203,101 @@ SIGNATURE = { FUSES ={.low = 0xde, .high = 0x99, .extended = 0xff,}; /* Put default MAC address in EEPROM */ +#if !JACKDAW_CONF_USE_SETTINGS uint8_t mac_address[8] EEMEM = {0x02, 0x12, 0x13, 0xff, 0xfe, 0x14, 0x15, 0x16}; -//uint8_t EEMEM mac_address[8]; //The raven webserver uses this EEMEM allocation -//uint8_t EEMEM server_name[16]; -//uint8_t EEMEM domain_name[30]; +#endif + +static uint8_t get_channel_from_eeprom() { +#if JACKDAW_CONF_USE_SETTINGS + uint8_t chan = settings_get_uint8(SETTINGS_KEY_CHANNEL, 0); + if(!chan) + chan = RF_CHANNEL; + return chan; +#else + uint8_t eeprom_channel; + uint8_t eeprom_check; + + eeprom_channel = eeprom_read_byte((uint8_t *)9); + eeprom_check = eeprom_read_byte((uint8_t *)10); + + if(eeprom_channel==~eeprom_check) + return eeprom_channel; + return 26; +#endif + +} + +static bool +get_eui64_from_eeprom(uint8_t macptr[8]) { +#if JACKDAW_CONF_USE_SETTINGS + size_t size = 8; + + if(settings_get(SETTINGS_KEY_EUI64, 0, (unsigned char*)macptr, &size)==SETTINGS_STATUS_OK) + return true; + + // Fallback to reading the traditional mac address + eeprom_read_block ((void *)macptr, 0, 8); +#else + eeprom_read_block ((void *)macptr, &mac_address, 8); +#endif + return macptr[0]!=0xFF; +} + +static bool +set_eui64_to_eeprom(const uint8_t macptr[8]) { +#if JACKDAW_CONF_USE_SETTINGS + return settings_set(SETTINGS_KEY_EUI64, macptr, 8)==SETTINGS_STATUS_OK; +#else + eeprom_write_block((void *)macptr, &mac_address, 8); + return true; +#endif +} + +static void +generate_new_eui64(uint8_t eui64[8]) { + eui64[0] = 0x02; + eui64[1] = rng_get_uint8(); + eui64[2] = rng_get_uint8(); + eui64[3] = 0xFF; + eui64[4] = 0xFE; + eui64[5] = rng_get_uint8(); + eui64[6] = rng_get_uint8(); + eui64[7] = rng_get_uint8(); +} + +static uint16_t +get_panid_from_eeprom(void) { +#if JACKDAW_CONF_USE_SETTINGS + uint16_t x = settings_get_uint16(SETTINGS_KEY_PAN_ID, 0); + if(!x) + x = IEEE802154_PANID; + return x; +#else + // TODO: Writeme! + return IEEE802154_PANID; +#endif +} + +static uint16_t +get_panaddr_from_eeprom(void) { +#if JACKDAW_CONF_USE_SETTINGS + return settings_get_uint16(SETTINGS_KEY_PAN_ADDR, 0); +#else + // TODO: Writeme! + return 0; +#endif +} + /*-------------------------------------------------------------------------*/ /*-----------------------------Low level initialization--------------------*/ static void initialize(void) { + watchdog_init(); + watchdog_start(); /* Initialize hardware */ -// Currently only used for finger detection for mass storage mode -#if USB_CONF_STORAGE + // Checks for "finger", jumps to DFU if present. init_lowlevel(); -#endif /* Clock */ clock_init(); @@ -221,7 +311,9 @@ static void initialize(void) { printf_P(PSTR("\n\n\n********BOOTING CONTIKI*********\n")); #endif #endif - + + Leds_init(); + /* rtimer init needed for low power protocols */ rtimer_init(); @@ -239,26 +331,52 @@ static void initialize(void) { /* Set addresses BEFORE starting tcpip process */ - memset(&addr, 0, sizeof(rimeaddr_t)); - AVR_ENTER_CRITICAL_REGION(); - eeprom_read_block ((void *)&addr.u8, &mac_address, 8); - AVR_LEAVE_CRITICAL_REGION(); - //RNDIS needs the mac address in reverse byte order - macLongAddr.u8[0]=addr.u8[7]; - macLongAddr.u8[1]=addr.u8[6]; - macLongAddr.u8[2]=addr.u8[5]; - macLongAddr.u8[3]=addr.u8[4]; - macLongAddr.u8[4]=addr.u8[3]; - macLongAddr.u8[5]=addr.u8[2]; - macLongAddr.u8[6]=addr.u8[1]; - macLongAddr.u8[7]=addr.u8[0]; - - memcpy(&uip_lladdr.addr, &addr.u8, 8); - rf230_set_pan_addr(IEEE802154_PANID, 0, (uint8_t *)&addr.u8); - rf230_set_channel(26); + memset(&tmp_addr, 0, sizeof(rimeaddr_t)); + if(!get_eui64_from_eeprom(tmp_addr.u8)) { +#if JACKDAW_CONF_RANDOM_MAC + // It doesn't look like we have a valid EUI-64 address + // so let's try to make a new one from scratch. + Leds_off(); + Led2_on(); + generate_new_eui64(tmp_addr.u8); + if(!set_eui64_to_eeprom(tmp_addr.u8)) { + watchdog_periodic(); + int i; + for(i=0;i<20;i++) { + Led1_toggle(); + _delay_ms(100); + } + Led1_off(); + } + Led2_off(); +#else + tmp_addr.u8[0]=0x02; + tmp_addr.u8[1]=0x12; + tmp_addr.u8[2]=0x13; + tmp_addr.u8[3]=0xff; + tmp_addr.u8[4]=0xfe; + tmp_addr.u8[5]=0x14; + tmp_addr.u8[6]=0x15; + tmp_addr.u8[7]=0x16; +#endif /* JACKDAW_CONF_RANDOM_MAC */ + } + - rimeaddr_set_node_addr(&addr); -// set_rime_addr(); + //Fix MAC address + init_net(); + + memcpy(&uip_lladdr.addr, &tmp_addr.u8, 8); + rf230_set_pan_addr( + get_panid_from_eeprom(), + get_panaddr_from_eeprom(), + (uint8_t *)&tmp_addr.u8 + ); + +#if JACKDAW_CONF_USE_SETTINGS + rf230_set_txpower(settings_get_uint8(SETTINGS_KEY_TXPOWER,0)); +#endif + + rimeaddr_set_node_addr(&tmp_addr); /* Initialize stack protocols */ queuebuf_init(); @@ -266,8 +384,10 @@ static void initialize(void) { NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); + rf230_set_channel(get_channel_from_eeprom()); + #if ANNOUNCE && USB_CONF_RS232 - printf_P(PSTR("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n"),addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); + printf_P(PSTR("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n\r"),tmp_addr.u8[0],tmp_addr.u8[1],tmp_addr.u8[2],tmp_addr.u8[3],tmp_addr.u8[4],tmp_addr.u8[5],tmp_addr.u8[6],tmp_addr.u8[7]); printf_P(PSTR("%s %s, channel %u"),NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel()); if (NETSTACK_RDC.channel_check_interval) { unsigned short tmp; @@ -305,13 +425,10 @@ static void initialize(void) { #if USB_CONF_CDC process_start(&cdc_process, NULL); #endif - process_start(&rndis_process, NULL); + process_start(&usb_eth_process, NULL); #if USB_CONF_STORAGE process_start(&storage_process, NULL); #endif - - //Fix MAC address - init_net(); #if ANNOUNCE #if USB_CONF_CDC @@ -320,7 +437,7 @@ static void initialize(void) { /* Allow USB CDC to keep up with printfs */ for (i=0;i<8000;i++) process_run(); #if RF230BB - printf_P(PSTR("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n\r"),addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); + printf_P(PSTR("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n\r"),tmp_addr.u8[0],tmp_addr.u8[1],tmp_addr.u8[2],tmp_addr.u8[3],tmp_addr.u8[4],tmp_addr.u8[5],tmp_addr.u8[6],tmp_addr.u8[7]); for (i=0;i<8000;i++) process_run(); printf_P(PSTR("%s %s, channel %u"),NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel()); if (NETSTACK_RDC.channel_check_interval) { @@ -359,6 +476,8 @@ main(void) while(1) { process_run(); + watchdog_periodic(); + #if TESTRTIMER if (rtimerflag) { //8 seconds is maximum interval, my jackdaw 4% slow rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); diff --git a/platform/avr-ravenusb/contiki-raven.h b/platform/avr-ravenusb/contiki-raven.h index ee03b50aa..d93ae17fc 100644 --- a/platform/avr-ravenusb/contiki-raven.h +++ b/platform/avr-ravenusb/contiki-raven.h @@ -45,8 +45,6 @@ // LED's for Raven USB #define Leds_init() (DDRD |= 0xA0, DDRE |= 0xC0) -#define Leds_on() (PORTD |= 0x80, PORTD &= ~0x40, PORTE &= ~0xC0) -#define Leds_off() (PORTD &= ~0x80, PORTD |= 0x20, PORTE |= 0xC0) #define Led0_on() (PORTD |= 0x80) #define Led1_on() (PORTD &= ~0x20) #define Led2_on() (PORTE &= ~0x80) @@ -59,6 +57,8 @@ #define Led1_toggle() (PIND |= 0x20) #define Led2_toggle() (PINE |= 0x80) #define Led3_toggle() (PINE |= 0x40) +#define Leds_on() (Led0_on(),Led1_on(),Led2_on(),Led3_on()) +#define Leds_off() (Led0_off(),Led1_off(),Led2_off(),Led3_off()) void init_lowlevel(void); diff --git a/platform/avr-ravenusb/fakeuip.c b/platform/avr-ravenusb/fakeuip.c deleted file mode 100644 index 9eb889623..000000000 --- a/platform/avr-ravenusb/fakeuip.c +++ /dev/null @@ -1,129 +0,0 @@ - -/* Various stub functions and uIP variables other code might need to - * compile. Allows you to save needing to compile all of uIP in just - * to get a few things */ - - -#include "uip.h" -#include - -#if CONTIKI_NO_NET - -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) - -uip_buf_t uip_aligned_buf; - -u16_t uip_len; - -struct uip_stats uip_stat; - -uip_lladdr_t uip_lladdr; - -static u8_t (* output)(uip_lladdr_t *); - -u8_t tcpip_output(uip_lladdr_t * lladdr){ - if(output != NULL) { - return output(lladdr); - } - return 0; -} -void tcpip_set_outputfunc(u8_t (* f)(uip_lladdr_t *)) { - output = f; -} - -u16_t htons(u16_t val) { return HTONS(val);} - - -#if THEOLDWAY -/********** UIP_NETIF.c **********/ -void -uip_netif_addr_autoconf_set(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr) -#else -/********** uip-ds6.c ************/ -void -uip_ds6_set_addr_iid(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr) -#endif /* THEOLDWAY */ -{ - /* We consider only links with IEEE EUI-64 identifier or - IEEE 48-bit MAC addresses */ -#if (UIP_LLADDR_LEN == 8) - memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN); - ipaddr->u8[8] ^= 0x02; -#elif (UIP_LLADDR_LEN == 6) - memcpy(ipaddr->u8 + 8, lladdr, 3); - ipaddr->u8[11] = 0xff; - ipaddr->u8[12] = 0xfe; - memcpy(ipaddr->u8 + 13, lladdr + 3, 3); - ipaddr->u8[8] ^= 0x02; -#else -#error cannot build interface address when UIP_LLADDR_LEN is not 6 or 8 - /* - UIP_LOG("CAN NOT BUIL INTERFACE IDENTIFIER"); - UIP_LOG("THE STACK IS GOING TO SHUT DOWN"); - UIP_LOG("THE HOST WILL BE UNREACHABLE"); - exit(-1); - */ -#endif -} - -/********** UIP.c ****************/ - -static u16_t -chksum(u16_t sum, const u8_t *data, u16_t len) -{ - u16_t t; - const u8_t *dataptr; - const u8_t *last_byte; - - dataptr = data; - last_byte = data + len - 1; - - while(dataptr < last_byte) { /* At least two more bytes */ - t = (dataptr[0] << 8) + dataptr[1]; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - dataptr += 2; - } - - if(dataptr == last_byte) { - t = (dataptr[0] << 8) + 0; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - } - - /* Return sum in host byte order. */ - return sum; -} - -static u16_t -upper_layer_chksum(u8_t proto) -{ - u16_t upper_layer_len; - u16_t sum; - - upper_layer_len = (((u16_t)(UIP_IP_BUF->len[0]) << 8) + UIP_IP_BUF->len[1]) ; - - /* First sum pseudoheader. */ - /* IP protocol and length fields. This addition cannot carry. */ - sum = upper_layer_len + proto; - /* Sum IP source and destination addresses. */ - sum = chksum(sum, (u8_t *)&UIP_IP_BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t)); - - /* Sum TCP header and data. */ - sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], - upper_layer_len); - - return (sum == 0) ? 0xffff : htons(sum); -} - -/*---------------------------------------------------------------------------*/ -u16_t -uip_icmp6chksum(void) -{ - return upper_layer_chksum(UIP_PROTO_ICMP6); -} -#endif /* CONTIKI_NO_NET */ diff --git a/platform/avr-ravenusb/rng.c b/platform/avr-ravenusb/rng.c new file mode 100644 index 000000000..a68f5c7d0 --- /dev/null +++ b/platform/avr-ravenusb/rng.c @@ -0,0 +1,218 @@ +// ADC-based strong RNG +// Very slow, but who cares---if you need fast random numbers, use a PRNG. + +#include "rng.h" +#include +#include +#include +#include "contiki.h" + +#ifndef RNG_CONF_USE_ADC +#define RNG_CONF_USE_ADC (!RNG_CONF_USE_RADIO_CLOCK && defined(ADMUX) && defined(ADCSRA) && defined(ADCSRB) && defined(ADSC) && defined(ADEN)) +#endif + +#ifndef RNG_CONF_USE_RADIO_CLOCK +#define RNG_CONF_USE_RADIO_CLOCK ((!RNG_CONF_USE_ADC) && RF230BB) +#endif + + +#define TEMPORAL_AGITATION() do { static uint8_t agitator; agitator*=97; agitator+=101; _delay_us(agitator>>1); } while (0); + + +// ------------------------------------------------------------------------- +#if RNG_CONF_USE_ADC +/* The hope is that there is enough noise in the LSB when pointing the +** ADC at the internal band-gap input and using the internal 2.56v +** AREF. +** +** TODO: Run some randomness tests on the output of this RNG! +*/ + +#define BITS_TO_SHIFT 9 + +#define ADC_CHAN_ADC1 ((0< + +//! Returns a byte with eight random bits. +/*! This function is very slow, and should only +** be used when true random entropy is required. +** The time it will take to complete is non-deterministic. +*/ +extern uint8_t rng_get_uint8(); + +#endif \ No newline at end of file diff --git a/platform/avr-ravenusb/sicslow_ethernet.c b/platform/avr-ravenusb/sicslow_ethernet.c index 4e84f1e7b..06e688e43 100644 --- a/platform/avr-ravenusb/sicslow_ethernet.c +++ b/platform/avr-ravenusb/sicslow_ethernet.c @@ -53,12 +53,14 @@ //TODO: Should be able to always use this SIMPLE mode, hence can remove the 'complex' mode permanently //TODO: RF230BB !SIMPLE works on XP, Ubuntu. SIMPLE works on Vista, W7. Find out why! -#if RF230BB -#define UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS 1 -#else -#define UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS 1 -#endif +#ifndef UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS +#define UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS 0 +#endif // ifndef UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS + +#ifndef UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR +#define UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR 1 +#endif // ifndef UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR #if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS /** @@ -255,12 +257,10 @@ #define MSB(u16) (((uint8_t *)&(u16))[1]) //!< Most significant byte of \a u16. #endif -#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS -#define rndis_ethernet_addr local_ethernet_addr -static uint64_t local_ethernet_addr = 0x3A3B3C3D3E3FULL; -#else -extern uint64_t rndis_ethernet_addr; -#endif +static const uint64_t simple_trans_ethernet_addr = 0x3E3D3C3B3AF2ULL; +extern uint64_t usb_ethernet_addr; + +extern uint64_t macLongAddr; #if !RF230BB extern void (*pinput)(const struct mac_driver *r); @@ -272,7 +272,6 @@ usbstick_mode_t usbstick_mode; uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan); uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan); uint8_t mac_createDefaultEthernetAddr(uint8_t * ethernet); -uint8_t memcmp_reverse(uint8_t * a, uint8_t * b, uint8_t num); void mac_ethhijack_nondata(const struct mac_driver *r); void mac_ethhijack(const struct mac_driver *r); @@ -294,18 +293,6 @@ uint8_t prefixBuffer[PREFIX_BUFFER_SIZE][3]; /* 6lowpan max size + ethernet header size + 1 */ uint8_t raw_buf[127+ UIP_LLH_LEN +1]; -/* RPL uses some core tcpip routines which includes another tcpip_input */ -#if UIP_CONF_IPV6_RPL -#warning --------------------------------------------------------------- -#warning For RPL comment out the tcpip_input routine in core/net/tcpip.c -#warning --------------------------------------------------------------- -#endif -void tcpip_input( void ) -{ -// printf("tcpip_input"); - mac_LowpanToEthernet(); -} - /** * \brief Perform any setup needed */ @@ -340,26 +327,27 @@ void mac_ethernetToLowpan(uint8_t * ethHeader) uip_lladdr_t destAddr; uip_lladdr_t *destAddrPtr = NULL; - PRINTF("Packet type: %x\n\r", ((struct uip_eth_hdr *) ethHeader)->type); + PRINTF("Packet type: 0x%04x\n\r", ntohs(((struct uip_eth_hdr *) ethHeader)->type)); //RUM doesn't support sending data #if UIP_CONF_USE_RUM return; #endif - //If not IPv6 we don't do anything - if (((struct uip_eth_hdr *) ethHeader)->type != HTONS(UIP_ETHTYPE_IPV6)) { - PRINTF("eth2low: Packet is not IPv6, dropping\n\r"); - // printf("!ipv6"); -#if !RF230BB - rndis_stat.txbad++; -#endif + // In sniffer mode we don't ever send anything + if (usbstick_mode.sendToRf == 0) { uip_len = 0; return; } - // In sniffer mode we don't ever send anything - if (usbstick_mode.sendToRf == 0) { + + //If not IPv6 we don't do anything + if (((struct uip_eth_hdr *) ethHeader)->type != HTONS(UIP_ETHTYPE_IPV6)) { + PRINTF("eth2low: Dropping packet w/type=0x%04x\n",ntohs(((struct uip_eth_hdr *) ethHeader)->type)); + // printf("!ipv6"); +#if !RF230BB + usb_eth_stat.txbad++; +#endif uip_len = 0; return; } @@ -377,21 +365,16 @@ void mac_ethernetToLowpan(uint8_t * ethHeader) (((struct uip_eth_hdr *) ethHeader)->dest.addr[4] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[5] == 0xFF) ) { /* IPv6 does not use broadcast addresses, hence this should not happen */ - PRINTF("eth2low: Ethernet broadcast address received, should not happen?\n\r"); + PRINTF("eth2low: Dropping broadcast packet\n\r"); #if !RF230BB - rndis_stat.txbad++; + usb_eth_stat.txbad++; #endif uip_len = 0; return; } else { -#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS - /* Simple Address Translation */ -#if RF230BB - if(memcmp((uint8_t *)&rndis_ethernet_addr, &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), 6) == 0) { -#else - if(memcmp_reverse((uint8_t *)&rndis_ethernet_addr, &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), 6) == 0) { -#endif + /* Simple Address Translation */ + if(memcmp((uint8_t *)&simple_trans_ethernet_addr, &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), 6) == 0) { //Addressed to us: make 802.15.4 address from IPv6 Address destAddr.addr[0] = UIP_IP_BUF->destipaddr.u8[8] ^ 0x02; destAddr.addr[1] = UIP_IP_BUF->destipaddr.u8[9]; @@ -403,20 +386,22 @@ void mac_ethernetToLowpan(uint8_t * ethHeader) destAddr.addr[7] = UIP_IP_BUF->destipaddr.u8[15]; destAddrPtr = &destAddr; - } else { + } +#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS + else { //Not addressed to us uip_len = 0; return; - } + } +#else /* Complex Address Translation */ -#else PRINTF("eth2low: Addressed packet received... "); //Check this returns OK if (mac_createSicslowpanLongAddr( &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), &destAddr) == 0) { PRINTF(" translation failed\n\r"); #if !RF230BB - rndis_stat.txbad++; + usb_eth_stat.txbad++; #endif uip_len = 0; return; @@ -441,13 +426,11 @@ void mac_ethernetToLowpan(uint8_t * ethHeader) #endif } - if (usbstick_mode.sendToRf){ - tcpip_output(destAddrPtr); + tcpip_output(destAddrPtr); #if !RF230BB - rndis_stat.txok++; + usb_eth_stat.txok++; #endif - } - + uip_len = 0; } @@ -488,13 +471,16 @@ void mac_LowpanToEthernet(void) (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); } -#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS - mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0])); -#else +#if !UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS //Source ethernet depends on node - mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]), - (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + if(!mac_createEthernetAddr( + (uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]), + (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER) + )) #endif + { + mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0])); + } //We only do address translation in network mode! if (usbstick_mode.translate) { @@ -508,7 +494,7 @@ void mac_LowpanToEthernet(void) usb_eth_send(uip_buf, uip_len, 1); #if !RF230BB - rndis_stat.rxok++; + usb_eth_stat.rxok++; #endif uip_len = 0; } @@ -653,13 +639,10 @@ int8_t mac_translateIcmpLinkLayer(lltype_t target) // printf("createsicslowpanlongaddr"); mac_createSicslowpanLongAddr(llbuf, (uip_lladdr_t *)UIP_ICMP_OPTS(icmp_opt_offset)->data); } else { - if (UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS) { - //Simple address translation always sets this as default +#if !UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS + if(!mac_createEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data, (uip_lladdr_t *)llbuf)) +#endif mac_createDefaultEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data); - } else { - //Complex address translation sets this as something special - mac_createEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data, (uip_lladdr_t *)llbuf); - } } //Adjust the length @@ -715,6 +698,15 @@ int8_t mac_translateIcmpLinkLayer(lltype_t target) */ uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) { +#if UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR + //Special case - if the address is our address, we just copy over what we know to be + //our 802.15.4 address + if (memcmp((uint8_t *)&usb_ethernet_addr, ethernet, 6) == 0) + { + memcpy((uint8_t *)lowpan, &macLongAddr, UIP_LLADDR_LEN); + return 1; + } +#endif #if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS @@ -733,56 +725,36 @@ uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) uint8_t index; #if UIP_LLADDR_LEN == 8 - //Special case - if the address is our address, we just copy over what we know to be - //our 802.15.4 address -#if RF230BB - if (memcmp((uint8_t *)&uip_lladdr.addr[2], ethernet, 6) == 0) { -// printf("here1"); - memcpy((uint8_t *)lowpan, uip_lladdr.addr, 8); -#else - if (memcmp_reverse((uint8_t *)&rndis_ethernet_addr, ethernet, 6) == 0) { - memcpy((uint8_t *)lowpan, &macLongAddr, 8); - byte_reverse((uint8_t *)lowpan, 8); -#endif - - return 1; - } - //Check if translate bit is set, hence we have to look up the prefix - if (ethernet[0] & TRANSLATE_BIT_MASK) { - + if((ethernet[0]&(TRANSLATE_BIT_MASK|MULTICAST_BIT_MASK|LOCAL_BIT_MASK)) == (TRANSLATE_BIT_MASK|LOCAL_BIT_MASK)) { //Get top bits index = ethernet[0] >> 3; - //Check this is plausible... - if (index >= prefixCounter) { - return 0; - } - //Copy over prefix lowpan->addr[0] = prefixBuffer[index][0]; - lowpan->addr[3] = prefixBuffer[index][1]; - lowpan->addr[4] = prefixBuffer[index][2]; - - //Bit is clear - //so we copy all six + lowpan->addr[1] = prefixBuffer[index][1]; + lowpan->addr[2] = prefixBuffer[index][2]; + lowpan->addr[3] = ethernet[1]; + lowpan->addr[4] = ethernet[2]; + + //Check this is plausible... + if (index >= prefixCounter) + return 0; } else { - // printf("here3"); lowpan->addr[0] = ethernet[0]; + lowpan->addr[1] = ethernet[1]; + lowpan->addr[2] = ethernet[2]; lowpan->addr[3] = 0xff; lowpan->addr[4] = 0xfe; } - //Copy over reamining five bytes - lowpan->addr[1] = ethernet[1]; - lowpan->addr[2] = ethernet[2]; - lowpan->addr[5] = ethernet[3]; - lowpan->addr[6] = ethernet[4]; - lowpan->addr[7] = ethernet[5]; + lowpan->addr[5] = ethernet[3]; + lowpan->addr[6] = ethernet[4]; + lowpan->addr[7] = ethernet[5]; #else //UIP_LLADDR != 8 + // Not sure when we would ever hit this case... uint8_t i; -// printf("here4"); for(i = 0; i < UIP_LLADDR_LEN; i++) { lowpan->addr[i] = ethernet[i]; } @@ -801,6 +773,14 @@ uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) */ uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) { +#if UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR + //Special case - if the address is our address, we just copy over what we know to be + //our 802.3 address + if (memcmp((uint8_t *)&macLongAddr, (uint8_t *)lowpan, UIP_LLADDR_LEN) == 0) { + usb_eth_get_mac_address(ethernet); + return 1; + } +#endif #if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS @@ -819,26 +799,11 @@ uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) #if UIP_LLADDR_LEN == 8 - //Special case - if the address is our address, we just copy over what we know to be - //our 802.3 address -#if RF230BB - if (memcmp(uip_lladdr.addr, (uint8_t *)lowpan, 8) == 0) { - memcpy(ethernet, &uip_lladdr.addr[2], 6); -#else - if (memcmp_reverse((uint8_t *)&macLongAddr, (uint8_t *)lowpan, 8) == 0) { - memcpy(ethernet, &rndis_ethernet_addr, 6); - byte_reverse(ethernet, 6); -#endif - - return 1; - } - - - //Check if we need to do anything: - if ((lowpan->addr[3] == 0xff) && (lowpan->addr[4] == 0xfe) && - ((lowpan->addr[0] & TRANSLATE_BIT_MASK) == 0) && - ((lowpan->addr[0] & MULTICAST_BIT_MASK) == 0) && - (lowpan->addr[0] & LOCAL_BIT_MASK)) { + //Check if we need to do anything: + if ((lowpan->addr[3] == 0xff) && (lowpan->addr[4] == 0xfe) && + ((lowpan->addr[0] & TRANSLATE_BIT_MASK) == 0) && + ((lowpan->addr[0] & MULTICAST_BIT_MASK) == 0) && + (lowpan->addr[0] & LOCAL_BIT_MASK)) { /** Nope: just copy over 6 bytes **/ ethernet[0] = lowpan->addr[0]; @@ -854,48 +819,45 @@ uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) /** Yes: need to store prefix **/ for (i = 0; i < prefixCounter; i++) { //Check the current prefix - if it fails, check next one - - - - if ((lowpan->addr[0] == prefixBuffer[i][0]) && - (lowpan->addr[3] == prefixBuffer[i][1]) && - (lowpan->addr[4] == prefixBuffer[i][2])) { - break; - } - - } - + if ((lowpan->addr[0] == prefixBuffer[i][0]) && + (lowpan->addr[1] == prefixBuffer[i][1]) && + (lowpan->addr[2] == prefixBuffer[i][2])) { + break; + } + } index = i; - //Deal with overflow, iron-fist style - if (index >= PREFIX_BUFFER_SIZE) { - index = 0; - prefixCounter = PREFIX_BUFFER_SIZE; - } else { - //Are we making a new one? - if (index == prefixCounter) { - prefixCounter++; - } - } + if (index >= PREFIX_BUFFER_SIZE) { + // Overflow. Fall back to simple translation. + // TODO: Implement me! + ethernet[0] = lowpan->addr[0]; + ethernet[1] = lowpan->addr[1]; + ethernet[2] = lowpan->addr[2]; + ethernet[3] = lowpan->addr[5]; + ethernet[4] = lowpan->addr[6]; + ethernet[5] = lowpan->addr[7]; + return 0; + } else { + //Are we making a new one? + if (index == prefixCounter) { + prefixCounter++; + prefixBuffer[index][0] = lowpan->addr[0]; + prefixBuffer[index][1] = lowpan->addr[1]; + prefixBuffer[index][2] = lowpan->addr[2]; + } - //Copy the prefix over, no matter if we have a new or old one - prefixBuffer[index][0] = lowpan->addr[0]; - prefixBuffer[index][1] = lowpan->addr[3]; - prefixBuffer[index][2] = lowpan->addr[4]; - - //Create ethernet MAC address now - ethernet[1] = lowpan->addr[1]; - ethernet[2] = lowpan->addr[2]; - ethernet[3] = lowpan->addr[5]; - ethernet[4] = lowpan->addr[6]; - ethernet[5] = lowpan->addr[7]; - - - ethernet[0] = TRANSLATE_BIT_MASK | LOCAL_BIT_MASK | (index << 3); - } + //Create ethernet MAC address now + ethernet[0] = TRANSLATE_BIT_MASK | LOCAL_BIT_MASK | (index << 3); + ethernet[1] = lowpan->addr[3]; + ethernet[2] = lowpan->addr[4]; + ethernet[3] = lowpan->addr[5]; + ethernet[4] = lowpan->addr[6]; + ethernet[5] = lowpan->addr[7]; + } + } #else //UIP_LLADDR_LEN != 8 - + // Not sure when we would ever hit this case... //Create ethernet MAC address now for(i = 0; i < UIP_LLADDR_LEN; i++) { ethernet[i] = lowpan->addr[i]; @@ -906,20 +868,15 @@ uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) return 1; } -#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS /** * \brief Create a 802.3 address (default) * \param ethernet Pointer to ethernet address */ uint8_t mac_createDefaultEthernetAddr(uint8_t * ethernet) { - memcpy(ethernet, &rndis_ethernet_addr, 6); -#if !RF230BB - byte_reverse(ethernet, 6); -#endif + memcpy(ethernet, &simple_trans_ethernet_addr, 6); return 1; } -#endif /** * \brief Slide the pointed to memory up a certain amount, * growing/shrinking a buffer @@ -952,6 +909,104 @@ void slide(uint8_t * data, uint8_t length, int16_t slide) } } +//#define ETHBUF(x) ((struct uip_eth_hdr *)x) +//#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +void +mac_log_802_15_4_tx(const uint8_t* buffer, size_t total_len) { + if (usbstick_mode.raw != 0) { + uint8_t sendlen; + + static uint8_t raw_buf[127+ UIP_LLH_LEN +1]; + + /* Get the raw frame */ + memcpy(&raw_buf[UIP_LLH_LEN], buffer, total_len); + sendlen = total_len; + + /* Setup generic ethernet stuff */ + ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A + + /* Check for broadcast message */ + if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { + ETHBUF(raw_buf)->dest.addr[0] = 0x33; + ETHBUF(raw_buf)->dest.addr[1] = 0x33; + ETHBUF(raw_buf)->dest.addr[2] = 0x00; + ETHBUF(raw_buf)->dest.addr[3] = 0x00; + ETHBUF(raw_buf)->dest.addr[4] = 0x80; + ETHBUF(raw_buf)->dest.addr[5] = 0x9A; + +/* + ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; + ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; + ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; + ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; +*/ + } else { + /* Otherwise we have a real address */ + mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]), + (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); + } + +// mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr); + mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0])); + + sendlen += UIP_LLH_LEN; + usb_eth_send(raw_buf, sendlen, 0); + } +} + +void +mac_log_802_15_4_rx(const uint8_t* buf, size_t len) { + if (usbstick_mode.raw != 0) { + uint8_t sendlen; + + /* Get the raw frame */ + memcpy(&raw_buf[UIP_LLH_LEN], buf, len); + sendlen = len; + + /* Setup generic ethernet stuff */ + ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A + + /* Check for broadcast message */ + if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { + ETHBUF(raw_buf)->dest.addr[0] = 0x33; + ETHBUF(raw_buf)->dest.addr[1] = 0x33; + ETHBUF(raw_buf)->dest.addr[2] = 0x00; + ETHBUF(raw_buf)->dest.addr[3] = 0x00; + ETHBUF(raw_buf)->dest.addr[4] = 0x80; + ETHBUF(raw_buf)->dest.addr[5] = 0x9A; +/* + ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; + ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; + ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; + ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; +*/ + } else { + /* Otherwise we have a real address */ + mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]), + (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); + } + +// mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr); + mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0])); + + sendlen += UIP_LLH_LEN; + usb_eth_send(raw_buf, sendlen, 0); + } +} + +bool +mac_is_send_enabled(void) { + return usbstick_mode.sendToRf; +} + +/** @} */ + + + +/** @} */ + + #if !RF230BB /*--------------------------------------------------------------------*/ /** \brief Process a received 6lowpan packet. Hijack function. @@ -997,58 +1052,7 @@ void mac_ethhijack_nondata(const struct mac_driver *r) */ void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result) { - uint8_t sendlen; - - /* Make sure we are supposed to do this */ - if (usbstick_mode.raw == 0) return; - -/* Get the raw frame */ - memcpy(&raw_buf[UIP_LLH_LEN], frame_result->frame, frame_result->length); - sendlen = frame_result->length; - - //Setup generic ethernet stuff - ETHBUF(raw_buf)->type = htons(UIP_ETHTYPE_802154); - - uint64_t tempaddr; - - - //Check for broadcast message - //if(rimeaddr_cmp((const rimeaddr_t *)destAddr, &rimeaddr_null)) { - if( ( p->fcf.destAddrMode == SHORTADDRMODE) && - ( p->dest_addr.addr16 == 0xffff) ) { - ETHBUF(raw_buf)->dest.addr[0] = 0x33; - ETHBUF(raw_buf)->dest.addr[1] = 0x33; - ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; - ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; - ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; - ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; - } else { - - tempaddr = p->dest_addr.addr64; - - byte_reverse((uint8_t *)&tempaddr, 8); - - //Otherwise we have a real address - mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]), - (uip_lladdr_t *)&tempaddr); - - } - - tempaddr = p->src_addr.addr64; - - byte_reverse((uint8_t *)&tempaddr, 8); - - mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]), - (uip_lladdr_t *)&tempaddr); - - PRINTF("Low2Eth: Sending 802.15.4 packet to ethernet\n\r"); - - sendlen += UIP_LLH_LEN; - - usb_eth_send(raw_buf, sendlen, 0); - rndis_stat.rxok++; - - return; + mac_log_802_15_4_tx(frame_result->frame, frame_result->length); } @@ -1059,67 +1063,11 @@ void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result) * The 6lowpan packet is put in packetbuf by the MAC. This routine passes * it directly to the ethernet layer without decompressing. */ -void mac_802154raw(const struct mac_driver *r) -{ - uint8_t sendlen; - - parsed_frame = sicslowmac_get_frame(); - - /* Get the raw frame */ - memcpy(&raw_buf[UIP_LLH_LEN], radio_frame_data(), radio_frame_length()); - sendlen = radio_frame_length(); - - //Setup generic ethernet stuff - ETHBUF(raw_buf)->type = htons(UIP_ETHTYPE_802154); - - - //Check for broadcast message - //if(rimeaddr_cmp((const rimeaddr_t *)destAddr, &rimeaddr_null)) { - if( ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) && - ( parsed_frame->dest_addr->addr16 == 0xffff) ) { - ETHBUF(raw_buf)->dest.addr[0] = 0x33; - ETHBUF(raw_buf)->dest.addr[1] = 0x33; - ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; - ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; - ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; - ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; - } else { - - //Otherwise we have a real address - mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]), - (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); - - } - - mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]), - (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - - PRINTF("Low2Eth: Sending 802.15.4 packet to ethernet\n\r"); - - sendlen += UIP_LLH_LEN; - - usb_eth_send(raw_buf, sendlen, 1); - rndis_stat.rxok++; - - return; +void mac_802154raw(const struct mac_driver *r) { + mac_log_802_15_4_tx(radio_frame_data(), radio_frame_length()); } - -uint8_t memcmp_reverse(uint8_t * a, uint8_t * b, uint8_t num) -{ - uint8_t i = 0; - - while(num) { - num--; - if (a[i] != b[num]) return 1; - i++; - } - - return 0; -} #endif /* !RF230BB */ -/** @} */ -/** @} */