1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-10-13 23:48:28 +03:00

Merge branch 'ide-1.5.x-library-to-new-format' into ide-1.5.x

This commit is contained in:
Cristian Maglie
2013-08-08 16:43:19 +02:00
752 changed files with 167609 additions and 10266 deletions

View File

@@ -1,88 +0,0 @@
/*
* Copyright (c) 2012 by Cristian Maglie <c.maglie@bug.st>
* Audio library for Arduino Due.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#include "Audio.h"
void AudioClass::begin(uint32_t sampleRate, uint32_t msPreBuffer) {
// Allocate a buffer to keep msPreBuffer milliseconds of audio
bufferSize = msPreBuffer * sampleRate / 1000;
if (bufferSize < 1024)
bufferSize = 1024;
buffer = (uint32_t *) malloc(bufferSize * sizeof(uint32_t));
half = buffer + bufferSize / 2;
last = buffer + bufferSize;
// Buffering starts from the beginning
running = buffer;
next = buffer;
// Start DAC
dac->begin(VARIANT_MCK / sampleRate);
dac->setOnTransmitEnd_CB(onTransmitEnd, this);
}
void AudioClass::end() {
dac->end();
free( buffer);
}
void AudioClass::prepare(int16_t *buffer, int S, int volume){
uint16_t *ubuffer = (uint16_t*) buffer;
for (int i=0; i<S; i++) {
// set volume amplitude (signed multiply)
buffer[i] = buffer[i] * volume / 1024;
// convert from signed 16 bit to unsigned 12 bit for DAC.
ubuffer[i] += 0x8000;
ubuffer[i] >>= 4;
}
}
size_t AudioClass::write(const uint32_t *data, size_t size) {
const uint32_t TAG = 0x10000000;
int i;
for (i = 0; i < size; i++) {
*next = data[i] | TAG;
next++;
if (next == half || next == last) {
enqueue();
while (next == running)
;
}
}
return i;
}
void AudioClass::enqueue() {
if (!dac->canQueue()) {
// DMA queue full
return;
}
if (next == half) {
// Enqueue the first half
dac->queueBuffer(buffer, bufferSize / 2);
} else {
// Enqueue the second half
dac->queueBuffer(half, bufferSize / 2);
next = buffer; // wrap around
}
}
void AudioClass::onTransmitEnd(void *_me) {
AudioClass *me = reinterpret_cast<AudioClass *> (_me);
if (me->running == me->buffer)
me->running = me->half;
else
me->running = me->buffer;
}
AudioClass Audio(DAC);

View File

@@ -1,57 +0,0 @@
/*
* Copyright (c) 2012 by Cristian Maglie <c.maglie@bug.st>
* Audio library for Arduino Due.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#ifndef AUDIO_H
#define AUDIO_H
#include "Arduino.h"
#include "Print.h"
#include "DAC.h"
class AudioClass : public Print {
public:
AudioClass(DACClass &_dac) : dac(&_dac) { };
void prepare(int16_t *buffer, int S, int volume);
void begin(uint32_t sampleRate, uint32_t msPreBuffer);
void end();
virtual size_t write(uint8_t c) { /* not implemented */ };
virtual size_t write(const uint8_t *data, size_t size) { return write(reinterpret_cast<const uint32_t*>(data), size/4) * 4; };
virtual size_t write(const uint16_t *data, size_t size) { return write(reinterpret_cast<const uint32_t*>(data), size/2) * 2; };
virtual size_t write(const int16_t *data, size_t size) { return write(reinterpret_cast<const uint32_t*>(data), size/2) * 2; };
virtual size_t write(const uint32_t *data, size_t size);
void debug() {
// Serial1.print(running-buffer, DEC);
// Serial1.print(" ");
// Serial1.print(current-buffer, DEC);
// Serial1.print(" ");
// Serial1.print(next-buffer, DEC);
// Serial1.print(" ");
// Serial1.println(last-buffer, DEC);
}
private:
void enqueue();
static void onTransmitEnd(void *me);
uint32_t bufferSize;
uint32_t *buffer;
uint32_t *half;
uint32_t *last;
uint32_t *volatile running;
uint32_t *volatile next;
uint32_t *cook(const uint32_t *buffer, size_t size);
DACClass *dac;
};
extern AudioClass Audio;
#endif

View File

@@ -1,138 +0,0 @@
/*
* Copyright (c) 2012 by Cristian Maglie <c.maglie@bug.st>
* DAC library for Arduino Due.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#include <DAC.h>
void DACClass::begin(uint32_t period) {
// Enable clock for DAC
pmc_enable_periph_clk(dacId);
dacc_reset(dac);
// Set transfer mode to double word
dacc_set_transfer_mode(dac, 1);
// Power save:
// sleep mode - 0 (disabled)
// fast wakeup - 0 (disabled)
dacc_set_power_save(dac, 0, 0);
// DAC refresh/startup timings:
// refresh - 0x08 (1024*8 dacc clocks)
// max speed mode - 0 (disabled)
// startup time - 0x10 (1024 dacc clocks)
dacc_set_timing(dac, 0x08, 0, DACC_MR_STARTUP_1024);
// Flexible channel selection with tags
dacc_enable_flexible_selection(dac);
// Set up analog current
dacc_set_analog_control(dac,
DACC_ACR_IBCTLCH0(0x02) |
DACC_ACR_IBCTLCH1(0x02) |
DACC_ACR_IBCTLDACCORE(0x01));
// Enable output channels
dacc_enable_channel(dac, 0);
dacc_enable_channel(dac, 1);
// Configure Timer Counter to trigger DAC
// --------------------------------------
pmc_enable_periph_clk(ID_TC1);
TC_Configure(TC0, 1,
TC_CMR_TCCLKS_TIMER_CLOCK2 | // Clock at MCR/8
TC_CMR_WAVE | // Waveform mode
TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC
TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR);
const uint32_t TC = period / 8;
TC_SetRA(TC0, 1, TC / 2);
TC_SetRC(TC0, 1, TC);
TC_Start(TC0, 1);
// Configure clock source for DAC (2 = TC0 Output Chan. 1)
dacc_set_trigger(dac, 2);
// Configure pins
PIO_Configure(g_APinDescription[DAC0].pPort,
g_APinDescription[DAC0].ulPinType,
g_APinDescription[DAC0].ulPin,
g_APinDescription[DAC0].ulPinConfiguration);
PIO_Configure(g_APinDescription[DAC1].pPort,
g_APinDescription[DAC1].ulPinType,
g_APinDescription[DAC1].ulPin,
g_APinDescription[DAC1].ulPinConfiguration);
// Enable interrupt controller for DAC
dacc_disable_interrupt(dac, 0xFFFFFFFF);
NVIC_DisableIRQ(isrId);
NVIC_ClearPendingIRQ(isrId);
NVIC_SetPriority(isrId, 0);
NVIC_EnableIRQ(isrId);
}
void DACClass::end() {
TC_Stop(TC0, 1);
NVIC_DisableIRQ(isrId);
dacc_disable_channel(dac, 0);
dacc_disable_channel(dac, 1);
}
bool DACClass::canQueue() {
return (dac->DACC_TNCR == 0);
}
size_t DACClass::queueBuffer(const uint32_t *buffer, size_t size) {
// Try the first PDC buffer
if ((dac->DACC_TCR == 0) && (dac->DACC_TNCR == 0)) {
dac->DACC_TPR = (uint32_t) buffer;
dac->DACC_TCR = size;
dac->DACC_PTCR = DACC_PTCR_TXTEN;
if (cb)
dacc_enable_interrupt(dac, DACC_IER_ENDTX);
return size;
}
// Try the second PDC buffer
if (dac->DACC_TNCR == 0) {
dac->DACC_TNPR = (uint32_t) buffer;
dac->DACC_TNCR = size;
dac->DACC_PTCR = DACC_PTCR_TXTEN;
if (cb)
dacc_enable_interrupt(dac, DACC_IER_ENDTX);
return size;
}
// PDC buffers full, try again later...
return 0;
}
void DACClass::setOnTransmitEnd_CB(OnTransmitEnd_CB _cb, void *_data) {
cb = _cb;
cbData = _data;
if (!cb)
dacc_disable_interrupt(dac, DACC_IDR_ENDTX);
}
void DACClass::onService() {
uint32_t sr = dac->DACC_ISR;
if (sr & DACC_ISR_ENDTX) {
// There is a free slot, enqueue data
dacc_disable_interrupt(dac, DACC_IDR_ENDTX);
if (cb)
cb(cbData);
}
}
DACClass DAC(DACC_INTERFACE, DACC_INTERFACE_ID, DACC_ISR_ID);
void DACC_ISR_HANDLER(void) {
DAC.onService();
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright (c) 2012 by Cristian Maglie <c.maglie@bug.st>
* DAC library for Arduino Due.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#ifndef DAC_INCLUDED
#define DAC_INCLUDED
#include "Arduino.h"
typedef void (*OnTransmitEnd_CB)(void *data);
class DACClass
{
public:
DACClass(Dacc *_dac, uint32_t _dacId, IRQn_Type _isrId) :
dac(_dac), dacId(_dacId), isrId(_isrId), cb(NULL) { };
void begin(uint32_t period);
void end();
bool canQueue();
size_t queueBuffer(const uint32_t *buffer, size_t size);
uint32_t *getCurrentQueuePointer();
void setOnTransmitEnd_CB(OnTransmitEnd_CB _cb, void *data);
void onService();
void enableInterrupts() { NVIC_EnableIRQ(isrId); };
void disableInterrupts() { NVIC_DisableIRQ(isrId); };
private:
Dacc *dac;
uint32_t dacId;
IRQn_Type isrId;
OnTransmitEnd_CB cb;
void *cbData;
};
extern DACClass DAC;
#endif

View File

@@ -1,83 +0,0 @@
/*
Simple Audio Player
Demonstrates the use of the Audio library for the Arduino Due
Hardware required :
* Arduino shield with a SD card on CS4
* A sound file named "test.wav" in the root directory of the SD card
* Speaker attched to ground and DAC0
Original by Massimo Banzi September 20, 2012
Modified by Scott Fitzgerald October 19, 2012
This example code is in the public domain
http://arduino.cc/en/Tutorial/SimpleAudioPlayer
*/
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
void setup()
{
// debug output at 9600 baud
Serial.begin(9600);
// setup SD-card
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println(" failed!");
return;
}
Serial.println(" done.");
// hi-speed SPI transfers
SPI.setClockDivider(4);
// 44100Khz stereo => 88200 sample rate
// 100 mSec of prebuffering.
Audio.begin(88200, 100);
}
void loop()
{
int count=0;
// open wave file from sdcard
File myFile = SD.open("test.wav");
if (!myFile) {
// if the file didn't open, print an error and stop
Serial.println("error opening test.wav");
while (true);
}
const int S=1024; // Number of samples to read in block
short buffer[S];
Serial.print("Playing");
// until the file is not finished
while (myFile.available()) {
// read from the file into buffer
myFile.read(buffer, sizeof(buffer));
// Prepare samples
int volume = 1024;
Audio.prepare(buffer, S, volume);
// Feed samples to audio
Audio.write(buffer, S);
// Every 100 block print a '.'
count++;
if (count == 100) {
Serial.print(".");
count = 0;
}
}
myFile.close();
Serial.println("End of file. Thank you for listening!");
while (true) ;
}

View File

@@ -1,21 +0,0 @@
#######################################
# Syntax Coloring Map For Audio
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Audio KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
prepare KEYWORD2
write KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -1,732 +0,0 @@
/*
Copyright (c) 2013 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "CAN.h"
#include "sn65hvd234.h"
/** Define the timemark mask. */
#define TIMEMARK_MASK 0x0000ffff
/* CAN timeout for synchronization. */
#define CAN_TIMEOUT 100000
/** The max value for CAN baudrate prescale. */
#define CAN_BAUDRATE_MAX_DIV 128
/** Define the scope for TQ. */
#define CAN_MIN_TQ_NUM 8
#define CAN_MAX_TQ_NUM 25
/** Define the fixed bit time value. */
#define CAN_BIT_SYNC 1
#define CAN_BIT_IPT 2
typedef struct {
uint8_t uc_tq; //! CAN_BIT_SYNC + uc_prog + uc_phase1 + uc_phase2 = uc_tq, 8 <= uc_tq <= 25.
uint8_t uc_prog; //! Propagation segment, (3-bits + 1), 1~8;
uint8_t uc_phase1; //! Phase segment 1, (3-bits + 1), 1~8;
uint8_t uc_phase2; //! Phase segment 2, (3-bits + 1), 1~8, CAN_BIT_IPT <= uc_phase2;
uint8_t uc_sjw; //! Resynchronization jump width, (2-bits + 1), min(uc_phase1, 4);
uint8_t uc_sp; //! Sample point value, 0~100 in percent.
} can_bit_timing_t;
/** Values of bit time register for different baudrates, Sample point = ((1 + uc_prog + uc_phase1) / uc_tq) * 100%. */
const can_bit_timing_t can_bit_time[] = {
{8, (2 + 1), (1 + 1), (1 + 1), (2 + 1), 75},
{9, (1 + 1), (2 + 1), (2 + 1), (1 + 1), 67},
{10, (2 + 1), (2 + 1), (2 + 1), (2 + 1), 70},
{11, (3 + 1), (2 + 1), (2 + 1), (3 + 1), 72},
{12, (2 + 1), (3 + 1), (3 + 1), (3 + 1), 67},
{13, (3 + 1), (3 + 1), (3 + 1), (3 + 1), 77},
{14, (3 + 1), (3 + 1), (4 + 1), (3 + 1), 64},
{15, (3 + 1), (4 + 1), (4 + 1), (3 + 1), 67},
{16, (4 + 1), (4 + 1), (4 + 1), (3 + 1), 69},
{17, (5 + 1), (4 + 1), (4 + 1), (3 + 1), 71},
{18, (4 + 1), (5 + 1), (5 + 1), (3 + 1), 67},
{19, (5 + 1), (5 + 1), (5 + 1), (3 + 1), 68},
{20, (6 + 1), (5 + 1), (5 + 1), (3 + 1), 70},
{21, (7 + 1), (5 + 1), (5 + 1), (3 + 1), 71},
{22, (6 + 1), (6 + 1), (6 + 1), (3 + 1), 68},
{23, (7 + 1), (7 + 1), (6 + 1), (3 + 1), 70},
{24, (6 + 1), (7 + 1), (7 + 1), (3 + 1), 67},
{25, (7 + 1), (7 + 1), (7 + 1), (3 + 1), 68}
};
/**
* \brief Configure CAN baudrate.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param ul_mck The input main clock for the CAN module.
* \param ul_baudrate Baudrate value (kB/s), allowed values:
* 1000, 800, 500, 250, 125, 50, 25, 10, 5.
*
* \retval Set the baudrate successfully or not.
*/
uint32_t CANRaw::set_baudrate(Can *p_can, uint32_t ul_mck, uint32_t ul_baudrate)
{
uint8_t uc_tq;
uint8_t uc_prescale;
uint32_t ul_mod;
uint32_t ul_cur_mod;
can_bit_timing_t *p_bit_time;
/* Check whether the baudrate prescale will be greater than the max divide value. */
if (((ul_mck + (ul_baudrate * CAN_MAX_TQ_NUM * 1000 - 1)) /
(ul_baudrate * CAN_MAX_TQ_NUM * 1000)) > CAN_BAUDRATE_MAX_DIV) {
return 0;
}
/* Check whether the input MCK is too small. */
if (ul_mck < ul_baudrate * CAN_MIN_TQ_NUM * 1000) {
return 0;
}
/* Initialize it as the minimum Time Quantum. */
uc_tq = CAN_MIN_TQ_NUM;
/* Initialize the remainder as the max value. When the remainder is 0, get the right TQ number. */
ul_mod = 0xffffffff;
/* Find out the approximate Time Quantum according to the baudrate. */
for (uint8_t i = CAN_MIN_TQ_NUM; i <= CAN_MAX_TQ_NUM; i++) {
if ((ul_mck / (ul_baudrate * i * 1000)) <= CAN_BAUDRATE_MAX_DIV) {
ul_cur_mod = ul_mck % (ul_baudrate * i * 1000);
if (ul_cur_mod < ul_mod){
ul_mod = ul_cur_mod;
uc_tq = i;
if (!ul_mod) {
break;
}
}
}
}
/* Calculate the baudrate prescale value. */
uc_prescale = ul_mck / (ul_baudrate * uc_tq * 1000);
/* Get the right CAN BIT Timing group. */
p_bit_time = (can_bit_timing_t *)&can_bit_time[uc_tq - CAN_MIN_TQ_NUM];
/* Before modifying the CANBR register, disable the CAN controller. */
//can_disable(p_can);
p_can->CAN_MR &= ~CAN_MR_CANEN;
/* Write into the CAN baudrate register. */
p_can->CAN_BR = CAN_BR_PHASE2(p_bit_time->uc_phase2 - 1) |
CAN_BR_PHASE1(p_bit_time->uc_phase1 - 1) |
CAN_BR_PROPAG(p_bit_time->uc_prog - 1) |
CAN_BR_SJW(p_bit_time->uc_sjw - 1) |
CAN_BR_BRP(uc_prescale - 1);
return 1;
}
/**
* \brief Initialize CAN controller.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param ul_mck CAN module input clock.
* \param ul_baudrate CAN communication baudrate in kbs.
*
* \retval 0 If failed to initialize the CAN module; otherwise successful.
*
* \note PMC clock for CAN peripheral should be enabled before calling this function.
*/
uint32_t CANRaw::init(Can *p_can, uint32_t ul_mck, uint32_t ul_baudrate)
{
uint32_t ul_flag;
uint32_t ul_tick;
/* Initialize the baudrate for CAN module. */
ul_flag = set_baudrate(p_can, ul_mck, ul_baudrate);
if (ul_flag == 0) {
return 0;
}
/* Reset the CAN eight message mailbox. */
can_reset_all_mailbox(p_can);
/* Enable the CAN controller. */
can_enable(p_can);
/* Wait until the CAN is synchronized with the bus activity. */
ul_flag = 0;
ul_tick = 0;
while (!(ul_flag & CAN_SR_WAKEUP) && (ul_tick < CAN_TIMEOUT)) {
ul_flag = can_get_status(p_can);
ul_tick++;
}
/* Timeout or the CAN module has been synchronized with the bus. */
if (CAN_TIMEOUT == ul_tick) {
return 0;
} else {
return 1;
}
}
/**
* \brief Enable CAN Controller.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::enable(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_CANEN;
}
/**
* \brief Disable CAN Controller.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::disable(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_CANEN;
}
/**
* \brief Disable CAN Controller low power mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::disable_low_power_mode(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_LPM;
}
/**
* \brief Enable CAN Controller low power mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::enable_low_power_mode(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_LPM;
}
/**
* \brief Disable CAN Controller autobaud/listen mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::disable_autobaud_listen_mode(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_ABM;
}
/**
* \brief Enable CAN Controller autobaud/listen mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::enable_autobaud_listen_mode(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_ABM;
}
/**
* \brief CAN Controller won't generate overload frame.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::disable_overload_frame(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_OVL;
}
/**
* \brief CAN Controller will generate an overload frame after each successful
* reception for mailboxes configured in Receive mode, Producer and Consumer.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::enable_overload_frame(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_OVL;
}
/**
* \brief Configure the timestamp capture point, at the start or the end of frame.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param ul_flag 0: Timestamp is captured at each start of frame;
* 1: Timestamp is captured at each end of frame.
*/
void CANRaw::set_timestamp_capture_point(Can *p_can, uint32_t ul_flag)
{
if (ul_flag) {
p_can->CAN_MR |= CAN_MR_TEOF;
} else {
p_can->CAN_MR &= ~CAN_MR_TEOF;
}
}
/**
* \brief Disable CAN Controller time triggered mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::disable_time_triggered_mode(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_TTM;
}
/**
* \brief Enable CAN Controller time triggered mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::enable_time_triggered_mode(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_TTM;
}
/**
* \brief Disable CAN Controller timer freeze.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::disable_timer_freeze(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_TIMFRZ;
}
/**
* \brief Enable CAN Controller timer freeze.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::enable_timer_freeze(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_TIMFRZ;
}
/**
* \brief Disable CAN Controller transmit repeat function.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::disable_tx_repeat(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_DRPT;
}
/**
* \brief Enable CAN Controller transmit repeat function.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::enable_tx_repeat(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_DRPT;
}
/**
* \brief Configure CAN Controller reception synchronization stage.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param ul_stage The reception stage to be configured.
*
* \note This is just for debug purpose only.
*/
void CANRaw::set_rx_sync_stage(Can *p_can, uint32_t ul_stage)
{
p_can->CAN_MR = (p_can->CAN_MR & ~CAN_MR_RXSYNC_Msk) | ul_stage;
}
/**
* \brief Enable CAN interrupt.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param dw_mask Interrupt to be enabled.
*/
void CANRaw::enable_interrupt(Can *p_can, uint32_t dw_mask)
{
p_can->CAN_IER = dw_mask;
}
/**
* \brief Disable CAN interrupt.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param dw_mask Interrupt to be disabled.
*/
void CANRaw::disable_interrupt(Can *p_can, uint32_t dw_mask)
{
p_can->CAN_IDR = dw_mask;
}
/**
* \brief Get CAN Interrupt Mask.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval CAN interrupt mask.
*/
uint32_t CANRaw::get_interrupt_mask(Can *p_can)
{
return (p_can->CAN_IMR);
}
/**
* \brief Get CAN status.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval CAN status.
*/
uint32_t CANRaw::get_status(Can *p_can)
{
return (p_can->CAN_SR);
}
/**
* \brief Get the 16-bit free-running internal timer count.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval The internal CAN free-running timer counter.
*/
uint32_t CANRaw::get_internal_timer_value(Can *p_can)
{
return (p_can->CAN_TIM);
}
/**
* \brief Get CAN timestamp register value.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval The timestamp value.
*/
uint32_t CANRaw::get_timestamp_value(Can *p_can)
{
return (p_can->CAN_TIMESTP);
}
/**
* \brief Get CAN transmit error counter.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval Transmit error counter.
*/
uint8_t CANRaw::get_tx_error_cnt(Can *p_can)
{
return (uint8_t) (p_can->CAN_ECR >> CAN_ECR_TEC_Pos);
}
/**
* \brief Get CAN receive error counter.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval Receive error counter.
*/
uint8_t CANRaw::get_rx_error_cnt(Can *p_can)
{
return (uint8_t) (p_can->CAN_ECR >> CAN_ECR_REC_Pos);
}
/**
* \brief Reset the internal free-running 16-bit timer.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \note If the internal timer counter is frozen, this function automatically
* re-enables it.
*/
void CANRaw::reset_internal_timer(Can *p_can)
{
p_can->CAN_TCR |= CAN_TCR_TIMRST;
}
/**
* \brief Send global transfer request.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_mask Mask for mailboxes that are requested to transfer.
*/
void CANRaw::global_send_transfer_cmd(Can *p_can, uint8_t uc_mask)
{
uint32_t ul_reg;
ul_reg = p_can->CAN_TCR & ((uint32_t)~GLOBAL_MAILBOX_MASK);
p_can->CAN_TCR = ul_reg | uc_mask;
}
/**
* \brief Send global abort request.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_mask Mask for mailboxes that are requested to abort.
*/
void CANRaw::global_send_abort_cmd(Can *p_can, uint8_t uc_mask)
{
uint32_t ul_reg;
ul_reg = p_can->CAN_ACR & ((uint32_t)~GLOBAL_MAILBOX_MASK);
p_can->CAN_ACR = ul_reg | uc_mask;
}
/**
* \brief Configure the timemark for the mailbox.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_index Indicate which mailbox is to be configured.
* \param us_cnt The timemark to be set.
*
* \note The timemark is active in Time Triggered mode only.
*/
void CANRaw::mailbox_set_timemark(Can *p_can, uint8_t uc_index, uint16_t us_cnt)
{
uint32_t ul_reg;
ul_reg = p_can->CAN_MB[uc_index].CAN_MMR & ((uint32_t)~TIMEMARK_MASK);
p_can->CAN_MB[uc_index].CAN_MMR = ul_reg | us_cnt;
}
/**
* \brief Get status of the mailbox.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_index Indicate which mailbox is to be read.
*
* \retval The mailbox status.
*/
uint32_t CANRaw::mailbox_get_status(Can *p_can, uint8_t uc_index)
{
return (p_can->CAN_MB[uc_index].CAN_MSR);
}
/**
* \brief Send single mailbox transfer request.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_index Indicate which mailbox is to be configured.
*/
void CANRaw::mailbox_send_transfer_cmd(Can *p_can, uint8_t uc_index)
{
p_can->CAN_MB[uc_index].CAN_MCR |= CAN_MCR_MTCR;
}
/**
* \brief Send single mailbox abort request.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_index Indicate which mailbox is to be configured.
*/
void CANRaw::mailbox_send_abort_cmd(Can *p_can, uint8_t uc_index)
{
p_can->CAN_MB[uc_index].CAN_MCR |= CAN_MCR_MACR;
}
/**
* \brief Initialize the mailbox in different mode and set up related configuration.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param p_mailbox Pointer to a CAN mailbox instance.
*/
void CANRaw::mailbox_init(Can *p_can, can_mb_conf_t *p_mailbox)
{
uint8_t uc_index;
uc_index = (uint8_t)p_mailbox->ul_mb_idx;
/* Check the object type of the mailbox. If it's used to disable the mailbox, reset the whole mailbox. */
if (!p_mailbox->uc_obj_type) {
p_can->CAN_MB[uc_index].CAN_MMR = 0;
p_can->CAN_MB[uc_index].CAN_MAM = 0;
p_can->CAN_MB[uc_index].CAN_MID = 0;
p_can->CAN_MB[uc_index].CAN_MDL = 0;
p_can->CAN_MB[uc_index].CAN_MDH = 0;
p_can->CAN_MB[uc_index].CAN_MCR = 0;
return;
}
/* Set the priority in Transmit mode. */
p_can->CAN_MB[uc_index].CAN_MMR = (p_can->CAN_MB[uc_index].CAN_MMR &
~CAN_MMR_PRIOR_Msk) | (p_mailbox-> uc_tx_prio << CAN_MMR_PRIOR_Pos);
/* Set the message ID and message acceptance mask for the mailbox in other modes. */
if (p_mailbox->uc_id_ver) {
p_can->CAN_MB[uc_index].CAN_MAM = p_mailbox->ul_id_msk | CAN_MAM_MIDE;
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id | CAN_MAM_MIDE;
} else {
p_can->CAN_MB[uc_index].CAN_MAM = p_mailbox->ul_id_msk;
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id;
}
/* Set up mailbox in one of the five different modes. */
p_can->CAN_MB[uc_index].CAN_MMR = (p_can->CAN_MB[uc_index].CAN_MMR &
~CAN_MMR_MOT_Msk) | (p_mailbox-> uc_obj_type << CAN_MMR_MOT_Pos);
}
/**
* \brief Read receive information for the mailbox.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param p_mailbox Pointer to a CAN mailbox instance.
*
* \retval Different CAN mailbox transfer status.
*
* \note Read the mailbox status before calling this function.
*/
uint32_t CANRaw::mailbox_read(Can *p_can, can_mb_conf_t *p_mailbox)
{
uint32_t ul_status;
uint8_t uc_index;
uint32_t ul_retval;
ul_retval = 0;
uc_index = (uint8_t)p_mailbox->ul_mb_idx;
ul_status = p_mailbox->ul_status;
/* Check whether there is overwriting happening in Receive with Overwrite mode,
or there're messages lost in Receive mode. */
if ((ul_status & CAN_MSR_MRDY) && (ul_status & CAN_MSR_MMI)) {
ul_retval = CAN_MAILBOX_RX_OVER;
}
/* Read the message family ID. */
p_mailbox->ul_fid = p_can->CAN_MB[uc_index].CAN_MFID & CAN_MFID_MFID_Msk;
/* Read received data length. */
p_mailbox->uc_length = (ul_status & CAN_MSR_MDLC_Msk) >> CAN_MSR_MDLC_Pos;
/* Read received data. */
p_mailbox->ul_datal = p_can->CAN_MB[uc_index].CAN_MDL;
if (p_mailbox->uc_length > 4) {
p_mailbox->ul_datah = p_can->CAN_MB[uc_index].CAN_MDH;
}
/* Read the mailbox status again to check whether the software needs to re-read mailbox data register. */
p_mailbox->ul_status = p_can->CAN_MB[uc_index].CAN_MSR;
ul_status = p_mailbox->ul_status;
if (ul_status & CAN_MSR_MMI) {
ul_retval |= CAN_MAILBOX_RX_NEED_RD_AGAIN;
} else {
ul_retval |= CAN_MAILBOX_TRANSFER_OK;
}
/* Enable next receive process. */
can_mailbox_send_transfer_cmd(p_can, uc_index);
return ul_retval;
}
/**
* \brief Prepare transmit information and write them into the mailbox.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param p_mailbox Pointer to a CAN mailbox instance.
*
* \retval CAN_MAILBOX_NOT_READY: Failed because mailbox isn't ready.
* CAN_MAILBOX_TRANSFER_OK: Successfully write message into mailbox.
*
* \note After calling this function, the mailbox message won't be sent out until
* can_mailbox_send_transfer_cmd() is called.
*/
uint32_t CANRaw::mailbox_write(Can *p_can, can_mb_conf_t *p_mailbox)
{
uint32_t ul_status;
uint8_t uc_index;
uc_index = (uint8_t)p_mailbox->ul_mb_idx;
/* Read the mailbox status firstly to check whether the mailbox is ready or not. */
p_mailbox->ul_status = can_mailbox_get_status(p_can, uc_index);
ul_status = p_mailbox->ul_status;
if (!(ul_status & CAN_MSR_MRDY)) {
return CAN_MAILBOX_NOT_READY;
}
/* Write transmit identifier. */
if (p_mailbox->uc_id_ver) {
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id | CAN_MAM_MIDE;
} else {
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id;
}
/* Write transmit data into mailbox data register. */
p_can->CAN_MB[uc_index].CAN_MDL = p_mailbox->ul_datal;
if (p_mailbox->uc_length > 4) {
p_can->CAN_MB[uc_index].CAN_MDH = p_mailbox->ul_datah;
}
/* Write transmit data length into mailbox control register. */
p_can->CAN_MB[uc_index].CAN_MCR = (p_can->CAN_MB[uc_index].CAN_MCR &
~CAN_MCR_MDLC_Msk) | CAN_MCR_MDLC(p_mailbox->uc_length);
return CAN_MAILBOX_TRANSFER_OK;
}
/**
* \brief Require to send out a remote frame.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param p_mailbox Pointer to a CAN mailbox instance.
*
* \retval CAN_MAILBOX_NOT_READY: Failed because mailbox isn't ready for transmitting message.
* CAN_MAILBOX_TRANSFER_OK: Successfully send out a remote frame.
*/
uint32_t CANRaw::mailbox_tx_remote_frame(Can *p_can, can_mb_conf_t *p_mailbox)
{
uint32_t ul_status;
uint8_t uc_index;
uc_index = (uint8_t)p_mailbox->ul_mb_idx;
/* Read the mailbox status firstly to check whether the mailbox is ready or not. */
p_mailbox->ul_status = p_can->CAN_MB[uc_index].CAN_MSR;
ul_status = p_mailbox->ul_status;
if (!(ul_status & CAN_MSR_MRDY)) {
return CAN_MAILBOX_NOT_READY;
}
/* Write transmit identifier. */
if (p_mailbox->uc_id_ver) {
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id | CAN_MAM_MIDE;
} else {
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id;
}
/* Set the RTR bit in the sent frame. */
p_can->CAN_MB[uc_index].CAN_MCR |= CAN_MCR_MRTR;
/* Set the MBx bit in the Transfer Command Register to send out the remote frame. */
can_global_send_transfer_cmd(p_can, (1 << uc_index));
return CAN_MAILBOX_TRANSFER_OK;
}
/**
* \brief Reset the eight mailboxes.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void CANRaw::reset_all_mailbox(Can *p_can)
{
can_mb_conf_t mb_config_t;
/* Set the mailbox object type parameter to disable the mailbox. */
mb_config_t.uc_obj_type = CAN_MB_DISABLE_MODE;
for (uint8_t i = 0; i < CANMB_NUMBER; i++) {
mb_config_t.ul_mb_idx = i;
can_mailbox_init(p_can, &mb_config_t);
}
}

View File

@@ -1,131 +0,0 @@
/*
Copyright (c) 2013 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _CAN_LIBRARY_
#define _CAN_LIBRARY_
#include "sn65hvd234.h"
/** Define the Mailbox mask for eight mailboxes. */
#define GLOBAL_MAILBOX_MASK 0x000000ff
/** Disable all interrupt mask */
#define CAN_DISABLE_ALL_INTERRUPT_MASK 0xffffffff
/** Define the typical baudrate for CAN communication in KHz. */
#define CAN_BPS_1000K 1000
#define CAN_BPS_800K 800
#define CAN_BPS_500K 500
#define CAN_BPS_250K 250
#define CAN_BPS_125K 125
#define CAN_BPS_50K 50
#define CAN_BPS_25K 25
#define CAN_BPS_10K 10
#define CAN_BPS_5K 5
/** Define the mailbox mode. */
#define CAN_MB_DISABLE_MODE 0
#define CAN_MB_RX_MODE 1
#define CAN_MB_RX_OVER_WR_MODE 2
#define CAN_MB_TX_MODE 3
#define CAN_MB_CONSUMER_MODE 4
#define CAN_MB_PRODUCER_MODE 5
/** Define CAN mailbox transfer status code. */
#define CAN_MAILBOX_TRANSFER_OK 0 //! Read from or write into mailbox successfully.
#define CAN_MAILBOX_NOT_READY 0x01 //! Receiver is empty or transmitter is busy.
#define CAN_MAILBOX_RX_OVER 0x02 //! Message overwriting happens or there're messages lost in different receive modes.
#define CAN_MAILBOX_RX_NEED_RD_AGAIN 0x04 //! Application needs to re-read the data register in Receive with Overwrite mode.
class CANRaw
{
protected:
/* CAN peripheral, set by constructor */
//Can* m_pCan ;
/* CAN Transceiver */
SSN65HVD234_Data m_Transceiver ;
/** CAN Transfer */
//can_mb_conf_t m_Mailbox;
private:
public:
// Constructor
//CANRawClass( Can* pCan ) ;
/**
* \defgroup sam_driver_can_group Controller Area Network (CAN) Driver
*
* See \ref sam_can_quickstart.
*
* \par Purpose
*
* The CAN controller provides all the features required to implement
* the serial communication protocol CAN defined by Robert Bosch GmbH,
* the CAN specification. This is a driver for configuration, enabling,
* disabling and use of the CAN peripheral.
*
* @{
*/
uint32_t set_baudrate(Can *p_can, uint32_t ul_mck, uint32_t ul_baudrate);
uint32_t init(Can *p_can, uint32_t ul_mck, uint32_t ul_baudrate);
void enable(Can *p_can);
void disable(Can *p_can);
void disable_low_power_mode(Can *p_can);
void enable_low_power_mode(Can *p_can);
void disable_autobaud_listen_mode(Can *p_can);
void enable_autobaud_listen_mode(Can *p_can);
void disable_overload_frame(Can *p_can);
void enable_overload_frame(Can *p_can);
void set_timestamp_capture_point(Can *p_can, uint32_t ul_flag);
void disable_time_triggered_mode(Can *p_can);
void enable_time_triggered_mode(Can *p_can);
void disable_timer_freeze(Can *p_can);
void enable_timer_freeze(Can *p_can);
void disable_tx_repeat(Can *p_can);
void enable_tx_repeat(Can *p_can);
void set_rx_sync_stage(Can *p_can, uint32_t ul_stage);
void enable_interrupt(Can *p_can, uint32_t dw_mask);
void disable_interrupt(Can *p_can, uint32_t dw_mask);
uint32_t get_interrupt_mask(Can *p_can);
uint32_t get_status(Can *p_can);
uint32_t get_internal_timer_value(Can *p_can);
uint32_t get_timestamp_value(Can *p_can);
uint8_t get_tx_error_cnt(Can *p_can);
uint8_t get_rx_error_cnt(Can *p_can);
void reset_internal_timer(Can *p_can);
void global_send_transfer_cmd(Can *p_can, uint8_t uc_mask);
void global_send_abort_cmd(Can *p_can, uint8_t uc_mask);
void mailbox_set_timemark(Can *p_can, uint8_t uc_index, uint16_t us_cnt);
uint32_t mailbox_get_status(Can *p_can, uint8_t uc_index);
void mailbox_send_transfer_cmd(Can *p_can, uint8_t uc_index);
void mailbox_send_abort_cmd(Can *p_can, uint8_t uc_index);
void mailbox_init(Can *p_can, can_mb_conf_t *p_mailbox);
uint32_t mailbox_read(Can *p_can, can_mb_conf_t *p_mailbox);
uint32_t mailbox_write(Can *p_can, can_mb_conf_t *p_mailbox);
uint32_t mailbox_tx_remote_frame(Can *p_can, can_mb_conf_t *p_mailbox);
void reset_all_mailbox(Can *p_can);
} ;
#endif // _CAN_LIBRARY_

View File

@@ -1,37 +0,0 @@
Controller Area network (CAN) API for Arduino Due
This is a beta release of the CAN API for Arduino Due. It contains the necessary classes and functions to configure, enable, disable and use of the CAN peripherals controllers embedded in the SAM3X8E core inside Arduino Due, and the two external SN65HVD234 transceivers.
This CAN API for Arduino Due is released together with a CAN sample1 sketch for the Arduino IDE 1.5.2 and it shows how to configure the CAN controllers and how to manage CAN message transfers. The two CAN controllers (CAN0 and CAN1) and two mailboxes (mailbox 0 and mailbox 1) are used: CAN0 mailbox 0 is configured as transmitter, and CAN1 mailbox 0 is configured as receiver. The communication baudrate is 1Mbit/s. The CAN0 controller tries to send on the bus messages through the mailbox 0 and waits for messages from mailbox 1 on CAN1 controller.
It is required to use the two CAN pins in Arduino Due, connected to the two external SN65HVD234transceivers in loop mode via a pair cable. The CAN message transaction can be monitored by a serial UART connection (115.2 Kbps, 8 data bits, no parity, 1 stop bit, no flux control) or serial monitor of the Arduino IDE 1.5.2 with autoscroll and newline modes activated.
Source files:
- CAN.cpp
- CAN.h
- sn65hvd234.c
- sn65hvd234.h
- variant.cpp
- variant.h
CAN files (.cpp .h) contain the CANRaw class with 38 functions.
sn65hvd234 files (.c .h) contain 7 driver functions.
The variant files (.cpp .h) are updates to the IDE 1.5.2 ones. Added initialization of the CAN pins in variant.cpp
and CAN pins definition in variant.h.
Hardware requirements:
- Arduino Due board
- Dual CAN transceiver shield
- Twisted shielded pair cable
Software requirements:
- Arduino IDE 1.5.2
- CAN API library
To perform the CAN sample 1 test, the pair cable needs to be connected between the two CAN ports as follows:
CANRX0 <-> CANRX0
CANRX1 <-> CANRX1
Once the CAN sample 1 and the CAN library are loaded in Arduino IDE 1.5.2, after serial monitor open or after a reset of the Arduino board, the following message should be displayed in the monitor terminal: Type CAN message to send. Then, an 8 digit message can be typed and after a return stroke of the keyboard, the following message should be displayed: Sent value=XXXXXXXX, where XXXXXXXX is the typed message. If the message was sent/received successfully, the following message should be displayed: CAN message received=XXXXXXX and End of test. Otherwise, there is a CAN communication error.

View File

@@ -1,128 +0,0 @@
// Arduino Due - CAN Sample 1
// Brief CAN example for Arduino Due
// Test the transmission from CAN0 Mailbox 0 to CAN1 Mailbox 0
// By Thibaut Viard/Wilfredo Molina 2012
// Required libraries
#include "variant.h"
#include <CAN.h>
#define TEST1_CAN_COMM_MB_IDX 0
#define TEST1_CAN_TRANSFER_ID 0x07
#define TEST1_CAN0_TX_PRIO 15
#define CAN_MSG_DUMMY_DATA 0x55AAAA55
// CAN frame max data length
#define MAX_CAN_FRAME_DATA_LEN 8
// CAN class
CANRaw CAN;
// Message variable to be send
uint32_t CAN_MSG_1 = 0;
// CAN0 Transceiver
SSN65HVD234_Data can0_transceiver;
// CAN1 Transceiver
SSN65HVD234_Data can1_transceiver;
// Define the struct for CAN message mailboxes needed
can_mb_conf_t can0_mailbox;
can_mb_conf_t can1_mailbox;
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
Serial.println("Type CAN message to send");
while (Serial.available() == 0);
}
void loop(){
while (Serial.available() > 0) {
CAN_MSG_1 = Serial.parseInt();
if (Serial.read() == '\n') {
Serial.print("Sent value= ");
Serial.println(CAN_MSG_1);
}
}
// Initialize CAN0 Transceiver
SN65HVD234_Init(&can0_transceiver);
SN65HVD234_SetRs(&can0_transceiver, 61);
SN65HVD234_SetEN(&can0_transceiver, 62);
// Enable CAN0 Transceiver
SN65HVD234_DisableLowPower(&can0_transceiver);
SN65HVD234_Enable(&can0_transceiver);
// Initialize CAN1 Transceiver
SN65HVD234_Init(&can1_transceiver);
SN65HVD234_SetRs(&can1_transceiver, 63);
SN65HVD234_SetEN(&can1_transceiver, 64);
// Enable CAN1 Transceiver
SN65HVD234_DisableLowPower(&can1_transceiver);
SN65HVD234_Enable(&can1_transceiver);
// Enable CAN0 & CAN1 clock
pmc_enable_periph_clk(ID_CAN0);
pmc_enable_periph_clk(ID_CAN1);
// Initialize CAN0 and CAN1, baudrate is 1Mb/s
CAN.init(CAN0, SystemCoreClock, CAN_BPS_1000K);
CAN.init(CAN1, SystemCoreClock, CAN_BPS_1000K);
// Initialize CAN1 mailbox 0 as receiver, frame ID is 0x07
// can_reset_mailbox_data(&can1_mailbox);
can1_mailbox.ul_mb_idx = TEST1_CAN_COMM_MB_IDX;
can1_mailbox.uc_obj_type = CAN_MB_RX_MODE;
can1_mailbox.ul_id_msk = CAN_MAM_MIDvA_Msk | CAN_MAM_MIDvB_Msk;
can1_mailbox.ul_id = CAN_MID_MIDvA(TEST1_CAN_TRANSFER_ID);
CAN.mailbox_init(CAN1, &can1_mailbox);
// Initialize CAN0 mailbox 0 as transmitter, transmit priority is 15
// can_reset_mailbox_data(&can0_mailbox);
can0_mailbox.ul_mb_idx = TEST1_CAN_COMM_MB_IDX;
can0_mailbox.uc_obj_type = CAN_MB_TX_MODE;
can0_mailbox.uc_tx_prio = TEST1_CAN0_TX_PRIO;
can0_mailbox.uc_id_ver = 0;
can0_mailbox.ul_id_msk = 0;
CAN.mailbox_init(CAN0, &can0_mailbox);
// Prepare transmit ID, data and data length in CAN0 mailbox 0
can0_mailbox.ul_id = CAN_MID_MIDvA(TEST1_CAN_TRANSFER_ID);
can0_mailbox.ul_datal = CAN_MSG_1;
can0_mailbox.ul_datah = CAN_MSG_DUMMY_DATA;
can0_mailbox.uc_length = MAX_CAN_FRAME_DATA_LEN;
CAN.mailbox_write(CAN0, &can0_mailbox);
// Send out the information in the mailbox
CAN.global_send_transfer_cmd(CAN0, CAN_TCR_MB0);
// Wait for CAN1 mailbox 0 to receive the data
while (!(CAN.mailbox_get_status(CAN1, 0) & CAN_MSR_MRDY)) {
}
// Read the received data from CAN1 mailbox 0
CAN.mailbox_read(CAN1, &can1_mailbox);
Serial.print("CAN message received= ");
Serial.println(can1_mailbox.ul_datal);
// Disable CAN0 Controller
CAN.disable(CAN0);
// Disable CAN0 Transceiver
SN65HVD234_EnableLowPower(&can0_transceiver);
SN65HVD234_Disable(&can0_transceiver);
// Disable CAN1 Controller
CAN.disable(CAN1);
// Disable CAN1 Transceiver
SN65HVD234_EnableLowPower(&can1_transceiver);
SN65HVD234_Disable(&can1_transceiver);
Serial.print("End of test");
while (1) {
}
}

View File

@@ -1,142 +0,0 @@
/*
Copyright (c) 2013 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* \file
*
* Implementation of the SN65HVD234 drivers.
*
*/
#include "sn65hvd234.h"
#include <string.h>
/**
* \brief Initialize SN65HVD234 component data
*
* \param pComponent pointer on SSN65HVD234_Data
*
* \return 0 if OK
*/
extern uint32_t SN65HVD234_Init( SSN65HVD234_Data* pComponent )
{
pComponent->dwPin_Rs=0u ;
pComponent->dwPin_EN=0u ;
return 0u ;
}
/**
* \brief Initialize Rs pin of transceiver
*
* \param pComponent pointer on SSN65HVD234_Data
* \param pPIO_Rs pointer on PIOx base for transceiver Rs pin
* \param dwPin_Rs PIO pin index for transceiver Rs pin
*
* \return 0 if OK
*/
extern uint32_t SN65HVD234_SetRs( SSN65HVD234_Data* pComponent, uint32_t dwPin_Rs )
{
pComponent->dwPin_Rs=dwPin_Rs ;
pinMode( dwPin_Rs, OUTPUT ) ;
return 0u ;
}
/**
* \brief Initialize EN pin of transceiver
*
* \param pComponent pointer on SSN65HVD234_Data
* \param pPIO_EN pointer on PIOx base for transceiver EN pin
* \param dwPin_EN PIO pin index for transceiver EN pin
*
* \return 0 if OK
*/
extern uint32_t SN65HVD234_SetEN( SSN65HVD234_Data* pComponent, uint32_t dwPin_EN )
{
pComponent->dwPin_EN=dwPin_EN ;
pinMode( dwPin_EN, OUTPUT ) ;
return 0u ;
}
/**
* \brief Enable transceiver
*
* \param pComponent pointer on SSN65HVD234_Data
*
* \return 0 if OK
*/
extern uint32_t SN65HVD234_Enable( SSN65HVD234_Data* pComponent )
{
// Raise EN of SN65HVD234 to High Level (Vcc)
digitalWrite( pComponent->dwPin_EN, HIGH ) ;
return 0u ;
}
/**
* \brief Disable transceiver
*
* \param pComponent pointer on SSN65HVD234_Data
*
* \return 0 if OK
*/
extern uint32_t SN65HVD234_Disable( SSN65HVD234_Data* pComponent )
{
// Lower EN of SN65HVD234 to Low Level (0.0v)
digitalWrite( pComponent->dwPin_EN, LOW ) ;
return 0u ;
}
/**
* \brief Turn component into lowpower mode
*
* \param pComponent pointer on SSN65HVD234_Data
*
* \return 0 if OK
*/
extern uint32_t SN65HVD234_EnableLowPower( SSN65HVD234_Data* pComponent )
{
// Raise Rs of SN65HVD234 to more than 0.75v
digitalWrite( pComponent->dwPin_Rs, HIGH ) ;
// Now, SN65HVD234 is only listening
return 0u ;
}
/**
* \brief Restore Normal mode by leaving lowpower mode
*
* \param pComponent pointer on SSN65HVD234_Data
*
* \return 0 if OK
*/
extern uint32_t SN65HVD234_DisableLowPower( SSN65HVD234_Data* pComponent )
{
// Lower Rs of SN65HVD234 to 0.0v < 0.33v
digitalWrite( pComponent->dwPin_Rs, LOW ) ;
return 0u ;
}

View File

@@ -1,58 +0,0 @@
/*
Copyright (c) 2013 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* \file
*
* Include Defines & macros for the SN65HVD234.
*/
#ifndef _CAN_SN65HVD234_
#define _CAN_SN65HVD234_
#include "variant.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _SSN65HVD234_Data
{
/** Rs Pin on PIO */
uint32_t dwPin_Rs ;
/** EN Pin on PIO */
uint32_t dwPin_EN ;
} SSN65HVD234_Data ;
extern uint32_t SN65HVD234_Init( SSN65HVD234_Data* pComponent ) ;
extern uint32_t SN65HVD234_SetRs( SSN65HVD234_Data* pComponent, uint32_t dwPin_Rs ) ;
extern uint32_t SN65HVD234_SetEN( SSN65HVD234_Data* pComponent, uint32_t dwPin_EN ) ;
extern uint32_t SN65HVD234_Enable( SSN65HVD234_Data* pComponent ) ;
extern uint32_t SN65HVD234_Disable( SSN65HVD234_Data* pComponent ) ;
extern uint32_t SN65HVD234_EnableLowPower( SSN65HVD234_Data* pComponent ) ;
extern uint32_t SN65HVD234_DisableLowPower( SSN65HVD234_Data* pComponent ) ;
#ifdef __cplusplus
}
#endif
#endif /* _CAN_SN65HVD234_ */

View File

@@ -1,480 +0,0 @@
// DHCP Library v0.3 - April 25, 2009
// Author: Jordan Terrell - blog.jordanterrell.com
#include "w5100.h"
#include <string.h>
#include <stdlib.h>
#include "Dhcp.h"
#include "Arduino.h"
#include "util.h"
int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
{
_dhcpLeaseTime=0;
_dhcpT1=0;
_dhcpT2=0;
_lastCheck=0;
_timeout = timeout;
_responseTimeout = responseTimeout;
// zero out _dhcpMacAddr
memset(_dhcpMacAddr, 0, 6);
reset_DHCP_lease();
memcpy((void*)_dhcpMacAddr, (void*)mac, 6);
_dhcp_state = STATE_DHCP_START;
return request_DHCP_lease();
}
void DhcpClass::reset_DHCP_lease(){
// zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
memset(_dhcpLocalIp, 0, 20);
}
//return:0 on error, 1 if request is sent and response is received
int DhcpClass::request_DHCP_lease(){
uint8_t messageType = 0;
// Pick an initial transaction ID
_dhcpTransactionId = random(1UL, 2000UL);
_dhcpInitialTransactionId = _dhcpTransactionId;
_dhcpUdpSocket.stop();
if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0)
{
// Couldn't get a socket
return 0;
}
presend_DHCP();
int result = 0;
unsigned long startTime = millis();
while(_dhcp_state != STATE_DHCP_LEASED)
{
if(_dhcp_state == STATE_DHCP_START)
{
_dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000));
_dhcp_state = STATE_DHCP_DISCOVER;
}
else if(_dhcp_state == STATE_DHCP_REREQUEST){
_dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
_dhcp_state = STATE_DHCP_REQUEST;
}
else if(_dhcp_state == STATE_DHCP_DISCOVER)
{
uint32_t respId;
messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_OFFER)
{
// We'll use the transaction ID that the offer came with,
// rather than the one we were up to
_dhcpTransactionId = respId;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000));
_dhcp_state = STATE_DHCP_REQUEST;
}
}
else if(_dhcp_state == STATE_DHCP_REQUEST)
{
uint32_t respId;
messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_ACK)
{
_dhcp_state = STATE_DHCP_LEASED;
result = 1;
//use default lease time if we didn't get it
if(_dhcpLeaseTime == 0){
_dhcpLeaseTime = DEFAULT_LEASE;
}
//calculate T1 & T2 if we didn't get it
if(_dhcpT1 == 0){
//T1 should be 50% of _dhcpLeaseTime
_dhcpT1 = _dhcpLeaseTime >> 1;
}
if(_dhcpT2 == 0){
//T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
_dhcpT2 = _dhcpT1 << 1;
}
_renewInSec = _dhcpT1;
_rebindInSec = _dhcpT2;
}
else if(messageType == DHCP_NAK)
_dhcp_state = STATE_DHCP_START;
}
if(messageType == 255)
{
messageType = 0;
_dhcp_state = STATE_DHCP_START;
}
if(result != 1 && ((millis() - startTime) > _timeout))
break;
}
// We're done with the socket now
_dhcpUdpSocket.stop();
_dhcpTransactionId++;
return result;
}
void DhcpClass::presend_DHCP()
{
}
void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
{
uint8_t buffer[32];
memset(buffer, 0, 32);
IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address
if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT))
{
// FIXME Need to return errors
return;
}
buffer[0] = DHCP_BOOTREQUEST; // op
buffer[1] = DHCP_HTYPE10MB; // htype
buffer[2] = DHCP_HLENETHERNET; // hlen
buffer[3] = DHCP_HOPS; // hops
// xid
unsigned long xid = htonl(_dhcpTransactionId);
memcpy(buffer + 4, &(xid), 4);
// 8, 9 - seconds elapsed
buffer[8] = ((secondsElapsed & 0xff00) >> 8);
buffer[9] = (secondsElapsed & 0x00ff);
// flags
unsigned short flags = htons(DHCP_FLAGSBROADCAST);
memcpy(buffer + 10, &(flags), 2);
// ciaddr: already zeroed
// yiaddr: already zeroed
// siaddr: already zeroed
// giaddr: already zeroed
//put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 28);
memset(buffer, 0, 32); // clear local buffer
memcpy(buffer, _dhcpMacAddr, 6); // chaddr
//put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 16);
memset(buffer, 0, 32); // clear local buffer
// leave zeroed out for sname && file
// put in W5100 transmit buffer x 6 (192 bytes)
for(int i = 0; i < 6; i++) {
_dhcpUdpSocket.write(buffer, 32);
}
// OPT - Magic Cookie
buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF);
buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF);
buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF);
buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF);
// OPT - message type
buffer[4] = dhcpMessageType;
buffer[5] = 0x01;
buffer[6] = messageType; //DHCP_REQUEST;
// OPT - client identifier
buffer[7] = dhcpClientIdentifier;
buffer[8] = 0x07;
buffer[9] = 0x01;
memcpy(buffer + 10, _dhcpMacAddr, 6);
// OPT - host name
buffer[16] = hostName;
buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address
strcpy((char*)&(buffer[18]), HOST_NAME);
printByte((char*)&(buffer[24]), _dhcpMacAddr[3]);
printByte((char*)&(buffer[26]), _dhcpMacAddr[4]);
printByte((char*)&(buffer[28]), _dhcpMacAddr[5]);
//put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 30);
if(messageType == DHCP_REQUEST)
{
buffer[0] = dhcpRequestedIPaddr;
buffer[1] = 0x04;
buffer[2] = _dhcpLocalIp[0];
buffer[3] = _dhcpLocalIp[1];
buffer[4] = _dhcpLocalIp[2];
buffer[5] = _dhcpLocalIp[3];
buffer[6] = dhcpServerIdentifier;
buffer[7] = 0x04;
buffer[8] = _dhcpDhcpServerIp[0];
buffer[9] = _dhcpDhcpServerIp[1];
buffer[10] = _dhcpDhcpServerIp[2];
buffer[11] = _dhcpDhcpServerIp[3];
//put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 12);
}
buffer[0] = dhcpParamRequest;
buffer[1] = 0x06;
buffer[2] = subnetMask;
buffer[3] = routersOnSubnet;
buffer[4] = dns;
buffer[5] = domainName;
buffer[6] = dhcpT1value;
buffer[7] = dhcpT2value;
buffer[8] = endOption;
//put data in W5100 transmit buffer
_dhcpUdpSocket.write(buffer, 9);
_dhcpUdpSocket.endPacket();
}
uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId)
{
uint8_t type = 0;
uint8_t opt_len = 0;
unsigned long startTime = millis();
while(_dhcpUdpSocket.parsePacket() <= 0)
{
if((millis() - startTime) > responseTimeout)
{
return 255;
}
delay(50);
}
// start reading in the packet
RIP_MSG_FIXED fixedMsg;
_dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED));
if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT)
{
transactionId = ntohl(fixedMsg.xid);
if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId))
{
// Need to read the rest of the packet here regardless
_dhcpUdpSocket.flush();
return 0;
}
memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4);
// Skip to the option part
// Doing this a byte at a time so we don't have to put a big buffer
// on the stack (as we don't have lots of memory lying around)
for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++)
{
_dhcpUdpSocket.read(); // we don't care about the returned byte
}
while (_dhcpUdpSocket.available() > 0)
{
switch (_dhcpUdpSocket.read())
{
case endOption :
break;
case padOption :
break;
case dhcpMessageType :
opt_len = _dhcpUdpSocket.read();
type = _dhcpUdpSocket.read();
break;
case subnetMask :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpSubnetMask, 4);
break;
case routersOnSubnet :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpGatewayIp, 4);
for (int i = 0; i < opt_len-4; i++)
{
_dhcpUdpSocket.read();
}
break;
case dns :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read(_dhcpDnsServerIp, 4);
for (int i = 0; i < opt_len-4; i++)
{
_dhcpUdpSocket.read();
}
break;
case dhcpServerIdentifier :
opt_len = _dhcpUdpSocket.read();
if( *((uint32_t*)_dhcpDhcpServerIp) == 0 ||
IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() )
{
_dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp));
}
else
{
// Skip over the rest of this option
while (opt_len--)
{
_dhcpUdpSocket.read();
}
}
break;
case dhcpT1value :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1));
_dhcpT1 = ntohl(_dhcpT1);
break;
case dhcpT2value :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2));
_dhcpT2 = ntohl(_dhcpT2);
break;
case dhcpIPaddrLeaseTime :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime));
_dhcpLeaseTime = ntohl(_dhcpLeaseTime);
_renewInSec = _dhcpLeaseTime;
break;
default :
opt_len = _dhcpUdpSocket.read();
// Skip over the rest of this option
while (opt_len--)
{
_dhcpUdpSocket.read();
}
break;
}
}
}
// Need to skip to end of the packet regardless here
_dhcpUdpSocket.flush();
return type;
}
/*
returns:
0/DHCP_CHECK_NONE: nothing happened
1/DHCP_CHECK_RENEW_FAIL: renew failed
2/DHCP_CHECK_RENEW_OK: renew success
3/DHCP_CHECK_REBIND_FAIL: rebind fail
4/DHCP_CHECK_REBIND_OK: rebind success
*/
int DhcpClass::checkLease(){
//this uses a signed / unsigned trick to deal with millis overflow
unsigned long now = millis();
signed long snow = (long)now;
int rc=DHCP_CHECK_NONE;
if (_lastCheck != 0){
signed long factor;
//calc how many ms past the timeout we are
factor = snow - (long)_secTimeout;
//if on or passed the timeout, reduce the counters
if ( factor >= 0 ){
//next timeout should be now plus 1000 ms minus parts of second in factor
_secTimeout = snow + 1000 - factor % 1000;
//how many seconds late are we, minimum 1
factor = factor / 1000 +1;
//reduce the counters by that mouch
//if we can assume that the cycle time (factor) is fairly constant
//and if the remainder is less than cycle time * 2
//do it early instead of late
if(_renewInSec < factor*2 )
_renewInSec = 0;
else
_renewInSec -= factor;
if(_rebindInSec < factor*2 )
_rebindInSec = 0;
else
_rebindInSec -= factor;
}
//if we have a lease but should renew, do it
if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){
_dhcp_state = STATE_DHCP_REREQUEST;
rc = 1 + request_DHCP_lease();
}
//if we have a lease or is renewing but should bind, do it
if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){
//this should basically restart completely
_dhcp_state = STATE_DHCP_START;
reset_DHCP_lease();
rc = 3 + request_DHCP_lease();
}
}
else{
_secTimeout = snow + 1000;
}
_lastCheck = now;
return rc;
}
IPAddress DhcpClass::getLocalIp()
{
return IPAddress(_dhcpLocalIp);
}
IPAddress DhcpClass::getSubnetMask()
{
return IPAddress(_dhcpSubnetMask);
}
IPAddress DhcpClass::getGatewayIp()
{
return IPAddress(_dhcpGatewayIp);
}
IPAddress DhcpClass::getDhcpServerIp()
{
return IPAddress(_dhcpDhcpServerIp);
}
IPAddress DhcpClass::getDnsServerIp()
{
return IPAddress(_dhcpDnsServerIp);
}
void DhcpClass::printByte(char * buf, uint8_t n ) {
char *str = &buf[1];
buf[0]='0';
do {
unsigned long m = n;
n /= 16;
char c = m - 16 * n;
*str-- = c < 10 ? c + '0' : c + 'A' - 10;
} while(n);
}

View File

@@ -1,178 +0,0 @@
// DHCP Library v0.3 - April 25, 2009
// Author: Jordan Terrell - blog.jordanterrell.com
#ifndef Dhcp_h
#define Dhcp_h
#include "EthernetUdp.h"
/* DHCP state machine. */
#define STATE_DHCP_START 0
#define STATE_DHCP_DISCOVER 1
#define STATE_DHCP_REQUEST 2
#define STATE_DHCP_LEASED 3
#define STATE_DHCP_REREQUEST 4
#define STATE_DHCP_RELEASE 5
#define DHCP_FLAGSBROADCAST 0x8000
/* UDP port numbers for DHCP */
#define DHCP_SERVER_PORT 67 /* from server to client */
#define DHCP_CLIENT_PORT 68 /* from client to server */
/* DHCP message OP code */
#define DHCP_BOOTREQUEST 1
#define DHCP_BOOTREPLY 2
/* DHCP message type */
#define DHCP_DISCOVER 1
#define DHCP_OFFER 2
#define DHCP_REQUEST 3
#define DHCP_DECLINE 4
#define DHCP_ACK 5
#define DHCP_NAK 6
#define DHCP_RELEASE 7
#define DHCP_INFORM 8
#define DHCP_HTYPE10MB 1
#define DHCP_HTYPE100MB 2
#define DHCP_HLENETHERNET 6
#define DHCP_HOPS 0
#define DHCP_SECS 0
#define MAGIC_COOKIE 0x63825363
#define MAX_DHCP_OPT 16
#define HOST_NAME "WIZnet"
#define DEFAULT_LEASE (900) //default lease time in seconds
#define DHCP_CHECK_NONE (0)
#define DHCP_CHECK_RENEW_FAIL (1)
#define DHCP_CHECK_RENEW_OK (2)
#define DHCP_CHECK_REBIND_FAIL (3)
#define DHCP_CHECK_REBIND_OK (4)
enum
{
padOption = 0,
subnetMask = 1,
timerOffset = 2,
routersOnSubnet = 3,
/* timeServer = 4,
nameServer = 5,*/
dns = 6,
/*logServer = 7,
cookieServer = 8,
lprServer = 9,
impressServer = 10,
resourceLocationServer = 11,*/
hostName = 12,
/*bootFileSize = 13,
meritDumpFile = 14,*/
domainName = 15,
/*swapServer = 16,
rootPath = 17,
extentionsPath = 18,
IPforwarding = 19,
nonLocalSourceRouting = 20,
policyFilter = 21,
maxDgramReasmSize = 22,
defaultIPTTL = 23,
pathMTUagingTimeout = 24,
pathMTUplateauTable = 25,
ifMTU = 26,
allSubnetsLocal = 27,
broadcastAddr = 28,
performMaskDiscovery = 29,
maskSupplier = 30,
performRouterDiscovery = 31,
routerSolicitationAddr = 32,
staticRoute = 33,
trailerEncapsulation = 34,
arpCacheTimeout = 35,
ethernetEncapsulation = 36,
tcpDefaultTTL = 37,
tcpKeepaliveInterval = 38,
tcpKeepaliveGarbage = 39,
nisDomainName = 40,
nisServers = 41,
ntpServers = 42,
vendorSpecificInfo = 43,
netBIOSnameServer = 44,
netBIOSdgramDistServer = 45,
netBIOSnodeType = 46,
netBIOSscope = 47,
xFontServer = 48,
xDisplayManager = 49,*/
dhcpRequestedIPaddr = 50,
dhcpIPaddrLeaseTime = 51,
/*dhcpOptionOverload = 52,*/
dhcpMessageType = 53,
dhcpServerIdentifier = 54,
dhcpParamRequest = 55,
/*dhcpMsg = 56,
dhcpMaxMsgSize = 57,*/
dhcpT1value = 58,
dhcpT2value = 59,
/*dhcpClassIdentifier = 60,*/
dhcpClientIdentifier = 61,
endOption = 255
};
typedef struct _RIP_MSG_FIXED
{
uint8_t op;
uint8_t htype;
uint8_t hlen;
uint8_t hops;
uint32_t xid;
uint16_t secs;
uint16_t flags;
uint8_t ciaddr[4];
uint8_t yiaddr[4];
uint8_t siaddr[4];
uint8_t giaddr[4];
uint8_t chaddr[6];
}RIP_MSG_FIXED;
class DhcpClass {
private:
uint32_t _dhcpInitialTransactionId;
uint32_t _dhcpTransactionId;
uint8_t _dhcpMacAddr[6];
uint8_t _dhcpLocalIp[4];
uint8_t _dhcpSubnetMask[4];
uint8_t _dhcpGatewayIp[4];
uint8_t _dhcpDhcpServerIp[4];
uint8_t _dhcpDnsServerIp[4];
uint32_t _dhcpLeaseTime;
uint32_t _dhcpT1, _dhcpT2;
signed long _renewInSec;
signed long _rebindInSec;
signed long _lastCheck;
unsigned long _timeout;
unsigned long _responseTimeout;
unsigned long _secTimeout;
uint8_t _dhcp_state;
EthernetUDP _dhcpUdpSocket;
int request_DHCP_lease();
void reset_DHCP_lease();
void presend_DHCP();
void send_DHCP_MESSAGE(uint8_t, uint16_t);
void printByte(char *, uint8_t);
uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId);
public:
IPAddress getLocalIp();
IPAddress getSubnetMask();
IPAddress getGatewayIp();
IPAddress getDhcpServerIp();
IPAddress getDnsServerIp();
int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
int checkLease();
};
#endif

View File

@@ -1,423 +0,0 @@
// Arduino DNS client for WizNet5100-based Ethernet shield
// (c) Copyright 2009-2010 MCQN Ltd.
// Released under Apache License, version 2.0
#include "w5100.h"
#include "EthernetUdp.h"
#include "util.h"
#include "Dns.h"
#include <string.h>
//#include <stdlib.h>
#include "Arduino.h"
#define SOCKET_NONE 255
// Various flags and header field values for a DNS message
#define UDP_HEADER_SIZE 8
#define DNS_HEADER_SIZE 12
#define TTL_SIZE 4
#define QUERY_FLAG (0)
#define RESPONSE_FLAG (1<<15)
#define QUERY_RESPONSE_MASK (1<<15)
#define OPCODE_STANDARD_QUERY (0)
#define OPCODE_INVERSE_QUERY (1<<11)
#define OPCODE_STATUS_REQUEST (2<<11)
#define OPCODE_MASK (15<<11)
#define AUTHORITATIVE_FLAG (1<<10)
#define TRUNCATION_FLAG (1<<9)
#define RECURSION_DESIRED_FLAG (1<<8)
#define RECURSION_AVAILABLE_FLAG (1<<7)
#define RESP_NO_ERROR (0)
#define RESP_FORMAT_ERROR (1)
#define RESP_SERVER_FAILURE (2)
#define RESP_NAME_ERROR (3)
#define RESP_NOT_IMPLEMENTED (4)
#define RESP_REFUSED (5)
#define RESP_MASK (15)
#define TYPE_A (0x0001)
#define CLASS_IN (0x0001)
#define LABEL_COMPRESSION_MASK (0xC0)
// Port number that DNS servers listen on
#define DNS_PORT 53
// Possible return codes from ProcessResponse
#define SUCCESS 1
#define TIMED_OUT -1
#define INVALID_SERVER -2
#define TRUNCATED -3
#define INVALID_RESPONSE -4
void DNSClient::begin(const IPAddress& aDNSServer)
{
iDNSServer = aDNSServer;
iRequestId = 0;
}
int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult)
{
// See if we've been given a valid IP address
const char* p =aIPAddrString;
while (*p &&
( (*p == '.') || (*p >= '0') || (*p <= '9') ))
{
p++;
}
if (*p == '\0')
{
// It's looking promising, we haven't found any invalid characters
p = aIPAddrString;
int segment =0;
int segmentValue =0;
while (*p && (segment < 4))
{
if (*p == '.')
{
// We've reached the end of a segment
if (segmentValue > 255)
{
// You can't have IP address segments that don't fit in a byte
return 0;
}
else
{
aResult[segment] = (byte)segmentValue;
segment++;
segmentValue = 0;
}
}
else
{
// Next digit
segmentValue = (segmentValue*10)+(*p - '0');
}
p++;
}
// We've reached the end of address, but there'll still be the last
// segment to deal with
if ((segmentValue > 255) || (segment > 3))
{
// You can't have IP address segments that don't fit in a byte,
// or more than four segments
return 0;
}
else
{
aResult[segment] = (byte)segmentValue;
return 1;
}
}
else
{
return 0;
}
}
int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult)
{
int ret =0;
// See if it's a numeric IP address
if (inet_aton(aHostname, aResult))
{
// It is, our work here is done
return 1;
}
// Check we've got a valid DNS server to use
if (iDNSServer == INADDR_NONE)
{
return INVALID_SERVER;
}
// Find a socket to use
if (iUdp.begin(1024+(millis() & 0xF)) == 1)
{
// Try up to three times
int retries = 0;
// while ((retries < 3) && (ret <= 0))
{
// Send DNS request
ret = iUdp.beginPacket(iDNSServer, DNS_PORT);
if (ret != 0)
{
// Now output the request data
ret = BuildRequest(aHostname);
if (ret != 0)
{
// And finally send the request
ret = iUdp.endPacket();
if (ret != 0)
{
// Now wait for a response
int wait_retries = 0;
ret = TIMED_OUT;
while ((wait_retries < 3) && (ret == TIMED_OUT))
{
ret = ProcessResponse(5000, aResult);
wait_retries++;
}
}
}
}
retries++;
}
// We're done with the socket now
iUdp.stop();
}
return ret;
}
uint16_t DNSClient::BuildRequest(const char* aName)
{
// Build header
// 1 1 1 1 1 1
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | ID |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | QDCOUNT |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | ANCOUNT |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | NSCOUNT |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// | ARCOUNT |
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
// As we only support one request at a time at present, we can simplify
// some of this header
iRequestId = millis(); // generate a random ID
uint16_t twoByteBuffer;
// FIXME We should also check that there's enough space available to write to, rather
// FIXME than assume there's enough space (as the code does at present)
iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId));
twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG);
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
twoByteBuffer = htons(1); // One question record
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
twoByteBuffer = 0; // Zero answer records
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
// and zero additional records
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
// Build question
const char* start =aName;
const char* end =start;
uint8_t len;
// Run through the name being requested
while (*end)
{
// Find out how long this section of the name is
end = start;
while (*end && (*end != '.') )
{
end++;
}
if (end-start > 0)
{
// Write out the size of this section
len = end-start;
iUdp.write(&len, sizeof(len));
// And then write out the section
iUdp.write((uint8_t*)start, end-start);
}
start = end+1;
}
// We've got to the end of the question name, so
// terminate it with a zero-length section
len = 0;
iUdp.write(&len, sizeof(len));
// Finally the type and class of question
twoByteBuffer = htons(TYPE_A);
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
twoByteBuffer = htons(CLASS_IN); // Internet class of question
iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer));
// Success! Everything buffered okay
return 1;
}
uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress)
{
uint32_t startTime = millis();
// Wait for a response packet
while(iUdp.parsePacket() <= 0)
{
if((millis() - startTime) > aTimeout)
return TIMED_OUT;
delay(50);
}
// We've had a reply!
// Read the UDP header
uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header
// Check that it's a response from the right server and the right port
if ( (iDNSServer != iUdp.remoteIP()) ||
(iUdp.remotePort() != DNS_PORT) )
{
// It's not from who we expected
return INVALID_SERVER;
}
// Read through the rest of the response
if (iUdp.available() < DNS_HEADER_SIZE)
{
return TRUNCATED;
}
iUdp.read(header, DNS_HEADER_SIZE);
uint16_t header_flags = htons(*((uint16_t*)&header[2]));
// Check that it's a response to this request
if ( ( iRequestId != (*((uint16_t*)&header[0])) ) ||
((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) )
{
// Mark the entire packet as read
iUdp.flush();
return INVALID_RESPONSE;
}
// Check for any errors in the response (or in our request)
// although we don't do anything to get round these
if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) )
{
// Mark the entire packet as read
iUdp.flush();
return -5; //INVALID_RESPONSE;
}
// And make sure we've got (at least) one answer
uint16_t answerCount = htons(*((uint16_t*)&header[6]));
if (answerCount == 0 )
{
// Mark the entire packet as read
iUdp.flush();
return -6; //INVALID_RESPONSE;
}
// Skip over any questions
for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++)
{
// Skip over the name
uint8_t len;
do
{
iUdp.read(&len, sizeof(len));
if (len > 0)
{
// Don't need to actually read the data out for the string, just
// advance ptr to beyond it
while(len--)
{
iUdp.read(); // we don't care about the returned byte
}
}
} while (len != 0);
// Now jump over the type and class
for (int i =0; i < 4; i++)
{
iUdp.read(); // we don't care about the returned byte
}
}
// Now we're up to the bit we're interested in, the answer
// There might be more than one answer (although we'll just use the first
// type A answer) and some authority and additional resource records but
// we're going to ignore all of them.
for (uint16_t i =0; i < answerCount; i++)
{
// Skip the name
uint8_t len;
do
{
iUdp.read(&len, sizeof(len));
if ((len & LABEL_COMPRESSION_MASK) == 0)
{
// It's just a normal label
if (len > 0)
{
// And it's got a length
// Don't need to actually read the data out for the string,
// just advance ptr to beyond it
while(len--)
{
iUdp.read(); // we don't care about the returned byte
}
}
}
else
{
// This is a pointer to a somewhere else in the message for the
// rest of the name. We don't care about the name, and RFC1035
// says that a name is either a sequence of labels ended with a
// 0 length octet or a pointer or a sequence of labels ending in
// a pointer. Either way, when we get here we're at the end of
// the name
// Skip over the pointer
iUdp.read(); // we don't care about the returned byte
// And set len so that we drop out of the name loop
len = 0;
}
} while (len != 0);
// Check the type and class
uint16_t answerType;
uint16_t answerClass;
iUdp.read((uint8_t*)&answerType, sizeof(answerType));
iUdp.read((uint8_t*)&answerClass, sizeof(answerClass));
// Ignore the Time-To-Live as we don't do any caching
for (int i =0; i < TTL_SIZE; i++)
{
iUdp.read(); // we don't care about the returned byte
}
// And read out the length of this answer
// Don't need header_flags anymore, so we can reuse it here
iUdp.read((uint8_t*)&header_flags, sizeof(header_flags));
if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) )
{
if (htons(header_flags) != 4)
{
// It's a weird size
// Mark the entire packet as read
iUdp.flush();
return -9;//INVALID_RESPONSE;
}
iUdp.read(aAddress.raw_address(), 4);
return SUCCESS;
}
else
{
// This isn't an answer type we're after, move onto the next one
for (uint16_t i =0; i < htons(header_flags); i++)
{
iUdp.read(); // we don't care about the returned byte
}
}
}
// Mark the entire packet as read
iUdp.flush();
// If we get here then we haven't found an answer
return -10;//INVALID_RESPONSE;
}

View File

@@ -1,41 +0,0 @@
// Arduino DNS client for WizNet5100-based Ethernet shield
// (c) Copyright 2009-2010 MCQN Ltd.
// Released under Apache License, version 2.0
#ifndef DNSClient_h
#define DNSClient_h
#include <EthernetUdp.h>
class DNSClient
{
public:
// ctor
void begin(const IPAddress& aDNSServer);
/** Convert a numeric IP address string into a four-byte IP address.
@param aIPAddrString IP address to convert
@param aResult IPAddress structure to store the returned IP address
@result 1 if aIPAddrString was successfully converted to an IP address,
else error code
*/
int inet_aton(const char *aIPAddrString, IPAddress& aResult);
/** Resolve the given hostname to an IP address.
@param aHostname Name to be resolved
@param aResult IPAddress structure to store the returned IP address
@result 1 if aIPAddrString was successfully converted to an IP address,
else error code
*/
int getHostByName(const char* aHostname, IPAddress& aResult);
protected:
uint16_t BuildRequest(const char* aName);
uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress);
IPAddress iDNSServer;
uint16_t iRequestId;
EthernetUDP iUdp;
};
#endif

View File

@@ -1,122 +0,0 @@
#include "w5100.h"
#include "Ethernet.h"
#include "Dhcp.h"
// XXX: don't make assumptions about the value of MAX_SOCK_NUM.
uint8_t EthernetClass::_state[MAX_SOCK_NUM] = {
0, 0, 0, 0 };
uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = {
0, 0, 0, 0 };
int EthernetClass::begin(uint8_t *mac_address)
{
static DhcpClass s_dhcp;
_dhcp = &s_dhcp;
// Initialise the basic info
W5100.init();
W5100.setMACAddress(mac_address);
W5100.setIPAddress(IPAddress(0,0,0,0).raw_address());
// Now try to get our config info from a DHCP server
int ret = _dhcp->beginWithDHCP(mac_address);
if(ret == 1)
{
// We've successfully found a DHCP server and got our configuration info, so set things
// accordingly
W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
_dnsServerAddress = _dhcp->getDnsServerIp();
}
return ret;
}
void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip)
{
// Assume the DNS server will be the machine on the same network as the local IP
// but with last octet being '1'
IPAddress dns_server = local_ip;
dns_server[3] = 1;
begin(mac_address, local_ip, dns_server);
}
void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server)
{
// Assume the gateway will be the machine on the same network as the local IP
// but with last octet being '1'
IPAddress gateway = local_ip;
gateway[3] = 1;
begin(mac_address, local_ip, dns_server, gateway);
}
void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway)
{
IPAddress subnet(255, 255, 255, 0);
begin(mac_address, local_ip, dns_server, gateway, subnet);
}
void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet)
{
W5100.init();
W5100.setMACAddress(mac);
W5100.setIPAddress(local_ip._address);
W5100.setGatewayIp(gateway._address);
W5100.setSubnetMask(subnet._address);
_dnsServerAddress = dns_server;
}
int EthernetClass::maintain(){
int rc = DHCP_CHECK_NONE;
if(_dhcp != NULL){
//we have a pointer to dhcp, use it
rc = _dhcp->checkLease();
switch ( rc ){
case DHCP_CHECK_NONE:
//nothing done
break;
case DHCP_CHECK_RENEW_OK:
case DHCP_CHECK_REBIND_OK:
//we might have got a new IP.
W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
_dnsServerAddress = _dhcp->getDnsServerIp();
break;
default:
//this is actually a error, it will retry though
break;
}
}
return rc;
}
IPAddress EthernetClass::localIP()
{
IPAddress ret;
W5100.getIPAddress(ret.raw_address());
return ret;
}
IPAddress EthernetClass::subnetMask()
{
IPAddress ret;
W5100.getSubnetMask(ret.raw_address());
return ret;
}
IPAddress EthernetClass::gatewayIP()
{
IPAddress ret;
W5100.getGatewayIp(ret.raw_address());
return ret;
}
IPAddress EthernetClass::dnsServerIP()
{
return _dnsServerAddress;
}
EthernetClass Ethernet;

View File

@@ -1,41 +0,0 @@
#ifndef ethernet_h
#define ethernet_h
#include <inttypes.h>
//#include "w5100.h"
#include "IPAddress.h"
#include "EthernetClient.h"
#include "EthernetServer.h"
#include "Dhcp.h"
#define MAX_SOCK_NUM 4
class EthernetClass {
private:
IPAddress _dnsServerAddress;
DhcpClass* _dhcp;
public:
static uint8_t _state[MAX_SOCK_NUM];
static uint16_t _server_port[MAX_SOCK_NUM];
// Initialise the Ethernet shield to use the provided MAC address and gain the rest of the
// configuration through DHCP.
// Returns 0 if the DHCP configuration failed, and 1 if it succeeded
int begin(uint8_t *mac_address);
void begin(uint8_t *mac_address, IPAddress local_ip);
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server);
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway);
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet);
int maintain();
IPAddress localIP();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsServerIP();
friend class EthernetClient;
friend class EthernetServer;
};
extern EthernetClass Ethernet;
#endif

View File

@@ -1,165 +0,0 @@
#include "w5100.h"
#include "socket.h"
extern "C" {
#include "string.h"
}
#include "Arduino.h"
#include "Ethernet.h"
#include "EthernetClient.h"
#include "EthernetServer.h"
#include "Dns.h"
uint16_t EthernetClient::_srcport = 1024;
EthernetClient::EthernetClient() : _sock(MAX_SOCK_NUM) {
}
EthernetClient::EthernetClient(uint8_t sock) : _sock(sock) {
}
int EthernetClient::connect(const char* host, uint16_t port) {
// Look up the host first
int ret = 0;
DNSClient dns;
IPAddress remote_addr;
dns.begin(Ethernet.dnsServerIP());
ret = dns.getHostByName(host, remote_addr);
if (ret == 1) {
return connect(remote_addr, port);
} else {
return ret;
}
}
int EthernetClient::connect(IPAddress ip, uint16_t port) {
if (_sock != MAX_SOCK_NUM)
return 0;
for (int i = 0; i < MAX_SOCK_NUM; i++) {
uint8_t s = W5100.readSnSR(i);
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
_sock = i;
break;
}
}
if (_sock == MAX_SOCK_NUM)
return 0;
_srcport++;
if (_srcport == 0) _srcport = 1024;
socket(_sock, SnMR::TCP, _srcport, 0);
if (!::connect(_sock, rawIPAddress(ip), port)) {
_sock = MAX_SOCK_NUM;
return 0;
}
while (status() != SnSR::ESTABLISHED) {
delay(1);
if (status() == SnSR::CLOSED) {
_sock = MAX_SOCK_NUM;
return 0;
}
}
return 1;
}
size_t EthernetClient::write(uint8_t b) {
return write(&b, 1);
}
size_t EthernetClient::write(const uint8_t *buf, size_t size) {
if (_sock == MAX_SOCK_NUM) {
setWriteError();
return 0;
}
if (!send(_sock, buf, size)) {
setWriteError();
return 0;
}
return size;
}
int EthernetClient::available() {
if (_sock != MAX_SOCK_NUM)
return W5100.getRXReceivedSize(_sock);
return 0;
}
int EthernetClient::read() {
uint8_t b;
if ( recv(_sock, &b, 1) > 0 )
{
// recv worked
return b;
}
else
{
// No data available
return -1;
}
}
int EthernetClient::read(uint8_t *buf, size_t size) {
return recv(_sock, buf, size);
}
int EthernetClient::peek() {
uint8_t b;
// Unlike recv, peek doesn't check to see if there's any data available, so we must
if (!available())
return -1;
::peek(_sock, &b);
return b;
}
void EthernetClient::flush() {
while (available())
read();
}
void EthernetClient::stop() {
if (_sock == MAX_SOCK_NUM)
return;
// attempt to close the connection gracefully (send a FIN to other side)
disconnect(_sock);
unsigned long start = millis();
// wait a second for the connection to close
while (status() != SnSR::CLOSED && millis() - start < 1000)
delay(1);
// if it hasn't closed, close it forcefully
if (status() != SnSR::CLOSED)
close(_sock);
EthernetClass::_server_port[_sock] = 0;
_sock = MAX_SOCK_NUM;
}
uint8_t EthernetClient::connected() {
if (_sock == MAX_SOCK_NUM) return 0;
uint8_t s = status();
return !(s == SnSR::LISTEN || s == SnSR::CLOSED || s == SnSR::FIN_WAIT ||
(s == SnSR::CLOSE_WAIT && !available()));
}
uint8_t EthernetClient::status() {
if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED;
return W5100.readSnSR(_sock);
}
// the next function allows us to use the client returned by
// EthernetServer::available() as the condition in an if-statement.
EthernetClient::operator bool() {
return _sock != MAX_SOCK_NUM;
}

View File

@@ -1,37 +0,0 @@
#ifndef ethernetclient_h
#define ethernetclient_h
#include "Arduino.h"
#include "Print.h"
#include "Client.h"
#include "IPAddress.h"
class EthernetClient : public Client {
public:
EthernetClient();
EthernetClient(uint8_t sock);
uint8_t status();
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(const char *host, uint16_t port);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
virtual int available();
virtual int read();
virtual int read(uint8_t *buf, size_t size);
virtual int peek();
virtual void flush();
virtual void stop();
virtual uint8_t connected();
virtual operator bool();
friend class EthernetServer;
using Print::write;
private:
static uint16_t _srcport;
uint8_t _sock;
};
#endif

View File

@@ -1,91 +0,0 @@
#include "w5100.h"
#include "socket.h"
extern "C" {
#include "string.h"
}
#include "Ethernet.h"
#include "EthernetClient.h"
#include "EthernetServer.h"
EthernetServer::EthernetServer(uint16_t port)
{
_port = port;
}
void EthernetServer::begin()
{
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);
if (client.status() == SnSR::CLOSED) {
socket(sock, SnMR::TCP, _port, 0);
listen(sock);
EthernetClass::_server_port[sock] = _port;
break;
}
}
}
void EthernetServer::accept()
{
int listening = 0;
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);
if (EthernetClass::_server_port[sock] == _port) {
if (client.status() == SnSR::LISTEN) {
listening = 1;
}
else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) {
client.stop();
}
}
}
if (!listening) {
begin();
}
}
EthernetClient EthernetServer::available()
{
accept();
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);
if (EthernetClass::_server_port[sock] == _port &&
(client.status() == SnSR::ESTABLISHED ||
client.status() == SnSR::CLOSE_WAIT)) {
if (client.available()) {
// XXX: don't always pick the lowest numbered socket.
return client;
}
}
}
return EthernetClient(MAX_SOCK_NUM);
}
size_t EthernetServer::write(uint8_t b)
{
return write(&b, 1);
}
size_t EthernetServer::write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
accept();
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);
if (EthernetClass::_server_port[sock] == _port &&
client.status() == SnSR::ESTABLISHED) {
n += client.write(buffer, size);
}
}
return n;
}

View File

@@ -1,22 +0,0 @@
#ifndef ethernetserver_h
#define ethernetserver_h
#include "Server.h"
class EthernetClient;
class EthernetServer :
public Server {
private:
uint16_t _port;
void accept();
public:
EthernetServer(uint16_t);
EthernetClient available();
virtual void begin();
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
using Print::write;
};
#endif

View File

@@ -1,218 +0,0 @@
/*
* Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield.
* This version only offers minimal wrapping of socket.c/socket.h
* Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/
*
* MIT License:
* Copyright (c) 2008 Bjoern Hartmann
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* bjoern@cs.stanford.edu 12/30/2008
*/
#include "w5100.h"
#include "socket.h"
#include "Ethernet.h"
#include "Udp.h"
#include "Dns.h"
/* Constructor */
EthernetUDP::EthernetUDP() : _sock(MAX_SOCK_NUM) {}
/* Start EthernetUDP socket, listening at local port PORT */
uint8_t EthernetUDP::begin(uint16_t port) {
if (_sock != MAX_SOCK_NUM)
return 0;
for (int i = 0; i < MAX_SOCK_NUM; i++) {
uint8_t s = W5100.readSnSR(i);
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
_sock = i;
break;
}
}
if (_sock == MAX_SOCK_NUM)
return 0;
_port = port;
_remaining = 0;
socket(_sock, SnMR::UDP, _port, 0);
return 1;
}
/* return number of bytes available in the current packet,
will return zero if parsePacket hasn't been called yet */
int EthernetUDP::available() {
return _remaining;
}
/* Release any resources being used by this EthernetUDP instance */
void EthernetUDP::stop()
{
if (_sock == MAX_SOCK_NUM)
return;
close(_sock);
EthernetClass::_server_port[_sock] = 0;
_sock = MAX_SOCK_NUM;
}
int EthernetUDP::beginPacket(const char *host, uint16_t port)
{
// Look up the host first
int ret = 0;
DNSClient dns;
IPAddress remote_addr;
dns.begin(Ethernet.dnsServerIP());
ret = dns.getHostByName(host, remote_addr);
if (ret == 1) {
return beginPacket(remote_addr, port);
} else {
return ret;
}
}
int EthernetUDP::beginPacket(IPAddress ip, uint16_t port)
{
_offset = 0;
return startUDP(_sock, rawIPAddress(ip), port);
}
int EthernetUDP::endPacket()
{
return sendUDP(_sock);
}
size_t EthernetUDP::write(uint8_t byte)
{
return write(&byte, 1);
}
size_t EthernetUDP::write(const uint8_t *buffer, size_t size)
{
uint16_t bytes_written = bufferData(_sock, _offset, buffer, size);
_offset += bytes_written;
return bytes_written;
}
int EthernetUDP::parsePacket()
{
// discard any remaining bytes in the last packet
flush();
if (W5100.getRXReceivedSize(_sock) > 0)
{
//HACK - hand-parse the UDP packet using TCP recv method
uint8_t tmpBuf[8];
int ret =0;
//read 8 header bytes and get IP and port from it
ret = recv(_sock,tmpBuf,8);
if (ret > 0)
{
_remoteIP = tmpBuf;
_remotePort = tmpBuf[4];
_remotePort = (_remotePort << 8) + tmpBuf[5];
_remaining = tmpBuf[6];
_remaining = (_remaining << 8) + tmpBuf[7];
// When we get here, any remaining bytes are the data
ret = _remaining;
}
return ret;
}
// There aren't any packets available
return 0;
}
int EthernetUDP::read()
{
uint8_t byte;
if ((_remaining > 0) && (recv(_sock, &byte, 1) > 0))
{
// We read things without any problems
_remaining--;
return byte;
}
// If we get here, there's no data available
return -1;
}
int EthernetUDP::read(unsigned char* buffer, size_t len)
{
if (_remaining > 0)
{
int got;
if (_remaining <= len)
{
// data should fit in the buffer
got = recv(_sock, buffer, _remaining);
}
else
{
// too much data for the buffer,
// grab as much as will fit
got = recv(_sock, buffer, len);
}
if (got > 0)
{
_remaining -= got;
return got;
}
}
// If we get here, there's no data available or recv failed
return -1;
}
int EthernetUDP::peek()
{
uint8_t b;
// Unlike recv, peek doesn't check to see if there's any data available, so we must.
// If the user hasn't called parsePacket yet then return nothing otherwise they
// may get the UDP header
if (!_remaining)
return -1;
::peek(_sock, &b);
return b;
}
void EthernetUDP::flush()
{
// could this fail (loop endlessly) if _remaining > 0 and recv in read fails?
// should only occur if recv fails after telling us the data is there, lets
// hope the w5100 always behaves :)
while (_remaining)
{
read();
}
}

View File

@@ -1,99 +0,0 @@
/*
* Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield.
* This version only offers minimal wrapping of socket.c/socket.h
* Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/
*
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
* might not happen often in practice, but in larger network topologies, a UDP
* packet can be received out of sequence.
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
* aware of it. Again, this may not be a concern in practice on small local networks.
* For more information, see http://www.cafeaulait.org/course/week12/35.html
*
* MIT License:
* Copyright (c) 2008 Bjoern Hartmann
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* bjoern@cs.stanford.edu 12/30/2008
*/
#ifndef ethernetudp_h
#define ethernetudp_h
#include <Udp.h>
#define UDP_TX_PACKET_MAX_SIZE 24
class EthernetUDP : public UDP {
private:
uint8_t _sock; // socket ID for Wiz5100
uint16_t _port; // local port to listen on
IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed
uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed
uint16_t _offset; // offset into the packet being sent
uint16_t _remaining; // remaining bytes of incoming packet yet to be processed
public:
EthernetUDP(); // Constructor
virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual void stop(); // Finish with the UDP socket
// Sending UDP packets
// Start building up a packet to send to the remote host specific in ip and port
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
virtual int beginPacket(IPAddress ip, uint16_t port);
// Start building up a packet to send to the remote host specific in host and port
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
virtual int beginPacket(const char *host, uint16_t port);
// Finish off this packet and send it
// Returns 1 if the packet was sent successfully, 0 if there was an error
virtual int endPacket();
// Write a single byte into the packet
virtual size_t write(uint8_t);
// Write size bytes from buffer into the packet
virtual size_t write(const uint8_t *buffer, size_t size);
using Print::write;
// Start processing the next available incoming packet
// Returns the size of the packet in bytes, or 0 if no packets are available
virtual int parsePacket();
// Number of bytes remaining in the current packet
virtual int available();
// Read a single byte from the current packet
virtual int read();
// Read up to len bytes from the current packet and place them into buffer
// Returns the number of bytes read, or 0 if none are available
virtual int read(unsigned char* buffer, size_t len);
// Read up to len characters from the current packet and place them into buffer
// Returns the number of characters read, or 0 if none are available
virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); };
// Return the next byte from the current packet without moving on to the next byte
virtual int peek();
virtual void flush(); // Finish reading the current packet
// Return the IP address of the host who sent the current incoming packet
virtual IPAddress remoteIP() { return _remoteIP; };
// Return the port of the host who sent the current incoming packet
virtual uint16_t remotePort() { return _remotePort; };
};
#endif

View File

@@ -1,222 +0,0 @@
/*
SCP1000 Barometric Pressure Sensor Display
Serves the output of a Barometric Pressure Sensor as a web page.
Uses the SPI library. For details on the sensor, see:
http://www.sparkfun.com/commerce/product_info.php?products_id=8161
http://www.vti.fi/en/support/obsolete_products/pressure_sensors/
This sketch adapted from Nathan Seidle's SCP1000 example for PIC:
http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip
Circuit:
SCP1000 sensor attached to pins 6,7, and 11 - 13:
DRDY: pin 6
CSB: pin 7
MOSI: pin 11
MISO: pin 12
SCK: pin 13
created 31 July 2010
by Tom Igoe
*/
#include <Ethernet.h>
// the sensor communicates using SPI, so include the library:
#include <SPI.h>
// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// assign an IP address for the controller:
IPAddress ip(192,168,1,20);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255, 255, 255, 0);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
//Sensor's memory register addresses:
const int PRESSURE = 0x1F; //3 most significant bits of pressure
const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure
const int TEMPERATURE = 0x21; //16 bit temperature reading
// pins used for the connection with the sensor
// the others you need are controlled by the SPI library):
const int dataReadyPin = 6;
const int chipSelectPin = 7;
float temperature = 0.0;
long pressure = 0;
long lastReadingTime = 0;
void setup() {
// start the SPI library:
SPI.begin();
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
// initalize the data ready and chip select pins:
pinMode(dataReadyPin, INPUT);
pinMode(chipSelectPin, OUTPUT);
Serial.begin(9600);
//Configure SCP1000 for low noise configuration:
writeRegister(0x02, 0x2D);
writeRegister(0x01, 0x03);
writeRegister(0x03, 0x02);
// give the sensor and Ethernet shield time to set up:
delay(1000);
//Set the sensor to high resolution mode tp start readings:
writeRegister(0x03, 0x0A);
}
void loop() {
// check for a reading no more than once a second.
if (millis() - lastReadingTime > 1000){
// if there's a reading ready, read it:
// don't do anything until the data ready pin is high:
if (digitalRead(dataReadyPin) == HIGH) {
getData();
// timestamp the last time you got a reading:
lastReadingTime = millis();
}
}
// listen for incoming Ethernet connections:
listenForEthernetClients();
}
void getData() {
Serial.println("Getting reading");
//Read the temperature data
int tempData = readRegister(0x21, 2);
// convert the temperature to celsius and display it:
temperature = (float)tempData / 20.0;
//Read the pressure data highest 3 bits:
byte pressureDataHigh = readRegister(0x1F, 1);
pressureDataHigh &= 0b00000111; //you only needs bits 2 to 0
//Read the pressure data lower 16 bits:
unsigned int pressureDataLow = readRegister(0x20, 2);
//combine the two parts into one 19-bit number:
pressure = ((pressureDataHigh << 16) | pressureDataLow)/4;
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" degrees C");
Serial.print("Pressure: " + String(pressure));
Serial.println(" Pa");
}
void listenForEthernetClients() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("Got a client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
// print the current readings, in HTML format:
client.print("Temperature: ");
client.print(temperature);
client.print(" degrees C");
client.println("<br />");
client.print("Pressure: " + String(pressure));
client.print(" Pa");
client.println("<br />");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
}
}
//Send a write command to SCP1000
void writeRegister(byte registerName, byte registerValue) {
// SCP1000 expects the register name in the upper 6 bits
// of the byte:
registerName <<= 2;
// command (read or write) goes in the lower two bits:
registerName |= 0b00000010; //Write command
// take the chip select low to select the device:
digitalWrite(chipSelectPin, LOW);
SPI.transfer(registerName); //Send register location
SPI.transfer(registerValue); //Send value to record into register
// take the chip select high to de-select:
digitalWrite(chipSelectPin, HIGH);
}
//Read register from the SCP1000:
unsigned int readRegister(byte registerName, int numBytes) {
byte inByte = 0; // incoming from the SPI read
unsigned int result = 0; // result to return
// SCP1000 expects the register name in the upper 6 bits
// of the byte:
registerName <<= 2;
// command (read or write) goes in the lower two bits:
registerName &= 0b11111100; //Read command
// take the chip select low to select the device:
digitalWrite(chipSelectPin, LOW);
// send the device the register you want to read:
int command = SPI.transfer(registerName);
// send a value of 0 to read the first byte returned:
inByte = SPI.transfer(0x00);
result = inByte;
// if there's more than one byte returned,
// shift the first byte then get the second byte:
if (numBytes > 1){
result = inByte << 8;
inByte = SPI.transfer(0x00);
result = result |inByte;
}
// take the chip select high to de-select:
digitalWrite(chipSelectPin, HIGH);
// return the result:
return(result);
}

View File

@@ -1,79 +0,0 @@
/*
Chat Server
A simple server that distributes any incoming messages to all
connected clients. To use telnet to your device's IP address and type.
You can see the client's input in the serial monitor as well.
Using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network.
// gateway and subnet are optional:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1, 177);
IPAddress gateway(192,168,1, 1);
IPAddress subnet(255, 255, 0, 0);
// telnet defaults to port 23
EthernetServer server(23);
boolean alreadyConnected = false; // whether or not the client was connected previously
void setup() {
// initialize the ethernet device
Ethernet.begin(mac, ip, gateway, subnet);
// start listening for clients
server.begin();
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Chat server address:");
Serial.println(Ethernet.localIP());
}
void loop() {
// wait for a new client:
EthernetClient client = server.available();
// when the client sends the first byte, say hello:
if (client) {
if (!alreadyConnected) {
// clead out the input buffer:
client.flush();
Serial.println("We have a new client");
client.println("Hello, client!");
alreadyConnected = true;
}
if (client.available() > 0) {
// read the bytes incoming from the client:
char thisChar = client.read();
// echo the bytes back to the client:
server.write(thisChar);
// echo the bytes to the server as well:
Serial.write(thisChar);
}
}
}

View File

@@ -1,160 +0,0 @@
/*
Cosm sensor client
This sketch connects an analog sensor to Cosm (http://www.cosm.com)
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.
This example has been updated to use version 2.0 of the cosm.com API.
To make it work, create a feed with a datastream, and give it the ID
sensor1. Or change the code below to match your feed.
Circuit:
* Analog sensor attached to analog in 0
* Ethernet shield attached to pins 10, 11, 12, 13
created 15 March 2010
updated 14 May 2012
by Tom Igoe with input from Usman Haque and Joe Saavedra
http://arduino.cc/en/Tutorial/CosmClient
This code is in the public domain.
*/
#include <SPI.h>
#include <Ethernet.h>
#define APIKEY "YOUR API KEY GOES HERE" // replace your Cosm api key here
#define FEEDID 00000 // replace your feed ID
#define USERAGENT "My Project" // user agent is the project name
// assign a MAC address for the ethernet controller.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(10,0,1,20);
// initialize the library instance:
EthernetClient client;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
// IPAddress server(216,52,233,121); // numeric IP for api.cosm.com
char server[] = "api.cosm.com"; // name address for cosm API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10L*1000L; // delay between updates to cosm.com
// the "L" is needed to use long type numbers
void setup() {
// start serial port:
Serial.begin(9600);
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// DHCP failed, so use a fixed IP address:
Ethernet.begin(mac, ip);
}
}
void loop() {
// read the analog sensor:
int sensorReading = analogRead(A0);
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
sendData(sensorReading);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
// this method makes a HTTP connection to the server:
void sendData(int thisData) {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.cosm.com");
client.print("X-ApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
// calculate the length of the sensor reading in bytes:
// 8 bytes for "sensor1," + number of digits of the data:
int thisLength = 8 + getLength(thisData);
client.println(thisLength);
// last pieces of the HTTP PUT request:
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
// here's the actual content of the PUT request:
client.print("sensor1,");
client.println(thisData);
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}
// This method calculates the number of digits in the
// sensor reading. Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:
int getLength(int someValue) {
// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0) {
dividend = dividend /10;
digits++;
}
// return the number of digits:
return digits;
}

View File

@@ -1,147 +0,0 @@
/*
Cosm sensor client with Strings
This sketch connects an analog sensor to Cosm (http://www.cosm.com)
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.
This example has been updated to use version 2.0 of the Cosm.com API.
To make it work, create a feed with two datastreams, and give them the IDs
sensor1 and sensor2. Or change the code below to match your feed.
This example uses the String library, which is part of the Arduino core from
version 0019.
Circuit:
* Analog sensor attached to analog in 0
* Ethernet shield attached to pins 10, 11, 12, 13
created 15 March 2010
updated 14 May 2012
by Tom Igoe with input from Usman Haque and Joe Saavedra
http://arduino.cc/en/Tutorial/CosmClientString
This code is in the public domain.
*/
#include <SPI.h>
#include <Ethernet.h>
#define APIKEY "YOUR API KEY GOES HERE" // replace your Cosm api key here
#define FEEDID 00000 // replace your feed ID
#define USERAGENT "My Project" // user agent is the project name
// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(10,0,1,20);
// initialize the library instance:
EthernetClient client;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
// IPAddress server(216,52,233,121); // numeric IP for api.cosm.com
char server[] = "api.cosm.com"; // name address for Cosm API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10L*1000L; // delay between updates to Cosm.com
// the "L" is needed to use long type numbers
void setup() {
// start serial port:
Serial.begin(9600);
// give the ethernet module time to boot up:
delay(1000);
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// DHCP failed, so use a fixed IP address:
Ethernet.begin(mac, ip);
}
}
void loop() {
// read the analog sensor:
int sensorReading = analogRead(A0);
// convert the data to a String to send it:
String dataString = "sensor1,";
dataString += sensorReading;
// you can append multiple readings to this String if your
// Cosm feed is set up to handle multiple values:
int otherSensorReading = analogRead(A1);
dataString += "\nsensor2,";
dataString += otherSensorReading;
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
sendData(dataString);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
// this method makes a HTTP connection to the server:
void sendData(String thisData) {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.cosm.com");
client.print("X-ApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
client.println(thisData.length());
// last pieces of the HTTP PUT request:
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
// here's the actual content of the PUT request:
client.println(thisData);
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}

View File

@@ -1,59 +0,0 @@
/*
DHCP-based IP printer
This sketch uses the DHCP extensions to the Ethernet library
to get an IP address via DHCP and print the address obtained.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
created 12 April 2011
modified 9 Apr 2012
by Tom Igoe
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {
0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
// this check is only needed on the Leonardo:
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
for(;;)
;
}
// print your local IP address:
Serial.print("My IP address: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}
Serial.println();
}
void loop() {
}

View File

@@ -1,87 +0,0 @@
/*
DHCP Chat Server
A simple server that distributes any incoming messages to all
connected clients. To use telnet to your device's IP address and type.
You can see the client's input in the serial monitor as well.
Using an Arduino Wiznet Ethernet shield.
THis version attempts to get an IP address using DHCP
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
created 21 May 2011
modified 9 Apr 2012
by Tom Igoe
Based on ChatServer example by David A. Mellis
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network.
// gateway and subnet are optional:
byte mac[] = {
0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
IPAddress ip(192,168,1,177);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,0,0);
// telnet defaults to port 23
EthernetServer server(23);
boolean gotAMessage = false; // whether or not you got a message from the client yet
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
// this check is only needed on the Leonardo:
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection:
Serial.println("Trying to get an IP address using DHCP");
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// initialize the ethernet device not using DHCP:
Ethernet.begin(mac, ip, gateway, subnet);
}
// print your local IP address:
Serial.print("My IP address: ");
ip = Ethernet.localIP();
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(ip[thisByte], DEC);
Serial.print(".");
}
Serial.println();
// start listening for clients
server.begin();
}
void loop() {
// wait for a new client:
EthernetClient client = server.available();
// when the client sends the first byte, say hello:
if (client) {
if (!gotAMessage) {
Serial.println("We have a new client");
client.println("Hello, client!");
gotAMessage = true;
}
// read the bytes incoming from the client:
char thisChar = client.read();
// echo the bytes back to the client:
server.write(thisChar);
// echo the bytes to the server as well:
Serial.print(thisChar);
}
}

View File

@@ -1,80 +0,0 @@
/*
DNS and DHCP-based Web client
This sketch connects to a website (http://www.google.com)
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe, based on work by Adrian McEwen
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
char serverName[] = "www.google.com";
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
while(true);
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(serverName, 80)) {
Serial.println("connected");
// Make a HTTP request:
client.println("GET /search?q=arduino HTTP/1.0");
client.println();
}
else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop()
{
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing forevermore:
while(true);
}
}

View File

@@ -1,163 +0,0 @@
/*
Pachube sensor client
This sketch connects an analog sensor to Pachube (http://www.pachube.com)
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.
This example has been updated to use version 2.0 of the Pachube.com API.
To make it work, create a feed with a datastream, and give it the ID
sensor1. Or change the code below to match your feed.
Circuit:
* Analog sensor attached to analog in 0
* Ethernet shield attached to pins 10, 11, 12, 13
created 15 March 2010
modified 9 Apr 2012
by Tom Igoe with input from Usman Haque and Joe Saavedra
http://arduino.cc/en/Tutorial/PachubeClient
This code is in the public domain.
*/
#include <SPI.h>
#include <Ethernet.h>
#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here
#define FEEDID 00000 // replace your feed ID
#define USERAGENT "My Project" // user agent is the project name
// assign a MAC address for the ethernet controller.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(10,0,1,20);
// initialize the library instance:
EthernetClient client;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
IPAddress server(216,52,233,122); // numeric IP for api.pachube.com
//char server[] = "api.pachube.com"; // name address for pachube API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between updates to Pachube.com
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// DHCP failed, so use a fixed IP address:
Ethernet.begin(mac, ip);
}
}
void loop() {
// read the analog sensor:
int sensorReading = analogRead(A0);
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
sendData(sensorReading);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
// this method makes a HTTP connection to the server:
void sendData(int thisData) {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.pachube.com");
client.print("X-PachubeApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
// calculate the length of the sensor reading in bytes:
// 8 bytes for "sensor1," + number of digits of the data:
int thisLength = 8 + getLength(thisData);
client.println(thisLength);
// last pieces of the HTTP PUT request:
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
// here's the actual content of the PUT request:
client.print("sensor1,");
client.println(thisData);
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}
// This method calculates the number of digits in the
// sensor reading. Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:
int getLength(int someValue) {
// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0) {
dividend = dividend /10;
digits++;
}
// return the number of digits:
return digits;
}

View File

@@ -1,154 +0,0 @@
/*
Pachube sensor client with Strings
This sketch connects an analog sensor to Pachube (http://www.pachube.com)
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.
This example has been updated to use version 2.0 of the pachube.com API.
To make it work, create a feed with two datastreams, and give them the IDs
sensor1 and sensor2. Or change the code below to match your feed.
This example uses the String library, which is part of the Arduino core from
version 0019.
Circuit:
* Analog sensor attached to analog in 0
* Ethernet shield attached to pins 10, 11, 12, 13
created 15 March 2010
modified 9 Apr 2012
by Tom Igoe with input from Usman Haque and Joe Saavedra
modified 8 September 2012
by Scott Fitzgerald
http://arduino.cc/en/Tutorial/PachubeClientString
This code is in the public domain.
*/
#include <SPI.h>
#include <Ethernet.h>
#define APIKEY "YOUR API KEY GOES HERE" // replace your Pachube api key here
#define FEEDID 00000 // replace your feed ID
#define USERAGENT "My Project" // user agent is the project name
// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(10,0,1,20);
// initialize the library instance:
EthernetClient client;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
IPAddress server(216,52,233,121); // numeric IP for api.pachube.com
//char server[] = "api.pachube.com"; // name address for pachube API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between updates to pachube.com
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// give the ethernet module time to boot up:
delay(1000);
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// DHCP failed, so use a fixed IP address:
Ethernet.begin(mac, ip);
}
}
void loop() {
// read the analog sensor:
int sensorReading = analogRead(A0);
// convert the data to a String to send it:
String dataString = "sensor1,";
dataString += sensorReading;
// you can append multiple readings to this String if your
// pachube feed is set up to handle multiple values:
int otherSensorReading = analogRead(A1);
dataString += "\nsensor2,";
dataString += otherSensorReading;
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
sendData(dataString);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
// this method makes a HTTP connection to the server:
void sendData(String thisData) {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.pachube.com");
client.print("X-pachubeApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
client.println(thisData.length());
// last pieces of the HTTP PUT request:
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
// here's the actual content of the PUT request:
client.println(thisData);
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}

View File

@@ -1,93 +0,0 @@
/*
Telnet client
This sketch connects to a a telnet server (http://www.google.com)
using an Arduino Wiznet Ethernet shield. You'll need a telnet server
to test this with.
Processing's ChatServer example (part of the network library) works well,
running on port 10002. It can be found as part of the examples
in the Processing application, available at
http://processing.org/
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
created 14 Sep 2010
modified 9 Apr 2012
by Tom Igoe
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,177);
// Enter the IP address of the server you're connecting to:
IPAddress server(1,1,1,1);
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 23 is default for telnet;
// if you're using Processing's ChatServer, use port 10002):
EthernetClient client;
void setup() {
// start the Ethernet connection:
Ethernet.begin(mac, ip);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, 10002)) {
Serial.println("connected");
}
else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop()
{
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// as long as there are bytes in the serial queue,
// read them and send them out the socket if it's open:
while (Serial.available() > 0) {
char inChar = Serial.read();
if (client.connected()) {
client.print(inChar);
}
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing:
while(true);
}
}

View File

@@ -1,135 +0,0 @@
/*
Twitter Client with Strings
This sketch connects to Twitter using an Ethernet shield. It parses the XML
returned, and looks for <text>this is a tweet</text>
You can use the Arduino Ethernet shield, or the Adafruit Ethernet shield,
either one will work, as long as it's got a Wiznet Ethernet module on board.
This example uses the DHCP routines in the Ethernet library which is part of the
Arduino core from version 1.0 beta 1
This example uses the String library, which is part of the Arduino core from
version 0019.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
created 21 May 2011
modified 9 Apr 2012
by Tom Igoe
This code is in the public domain.
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x01 };
IPAddress ip(192,168,1,20);
// initialize the library instance:
EthernetClient client;
const unsigned long requestInterval = 60000; // delay between requests
char serverName[] = "api.twitter.com"; // twitter URL
boolean requested; // whether you've made a request since connecting
unsigned long lastAttemptTime = 0; // last time you connected to the server, in milliseconds
String currentLine = ""; // string to hold the text from server
String tweet = ""; // string to hold the tweet
boolean readingTweet = false; // if you're currently reading the tweet
void setup() {
// reserve space for the strings:
currentLine.reserve(256);
tweet.reserve(150);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// attempt a DHCP connection:
Serial.println("Attempting to get an IP address using DHCP:");
if (!Ethernet.begin(mac)) {
// if DHCP fails, start with a hard-coded address:
Serial.println("failed to get an IP address using DHCP, trying manually");
Ethernet.begin(mac, ip);
}
Serial.print("My address:");
Serial.println(Ethernet.localIP());
// connect to Twitter:
connectToServer();
}
void loop()
{
if (client.connected()) {
if (client.available()) {
// read incoming bytes:
char inChar = client.read();
// add incoming byte to end of line:
currentLine += inChar;
// if you get a newline, clear the line:
if (inChar == '\n') {
currentLine = "";
}
// if the current line ends with <text>, it will
// be followed by the tweet:
if ( currentLine.endsWith("<text>")) {
// tweet is beginning. Clear the tweet string:
readingTweet = true;
tweet = "";
}
// if you're currently reading the bytes of a tweet,
// add them to the tweet String:
if (readingTweet) {
if (inChar != '<') {
tweet += inChar;
}
else {
// if you got a "<" character,
// you've reached the end of the tweet:
readingTweet = false;
Serial.println(tweet);
// close the connection to the server:
client.stop();
}
}
}
}
else if (millis() - lastAttemptTime > requestInterval) {
// if you're not connected, and two minutes have passed since
// your last connection, then attempt to connect again:
connectToServer();
}
}
void connectToServer() {
// attempt to connect, and wait a millisecond:
Serial.println("connecting to server...");
if (client.connect(serverName, 80)) {
Serial.println("making HTTP request...");
// make HTTP GET request to twitter:
client.println("GET /1/statuses/user_timeline.xml?screen_name=arduino&count=1 HTTP/1.1");
client.println("HOST: api.twitter.com");
client.println();
}
// note the time of this connect attempt:
lastAttemptTime = millis();
}

View File

@@ -1,120 +0,0 @@
/*
UDPSendReceive
This sketch receives UDP message strings, prints them to the serial port
and sends an "acknowledge" string back to the sender
A Processing sketch is included at the end of file that can be used to send
and received messages for testing with a computer.
created 21 Aug 2010
by Michael Margolis
This code is in the public domain.
*/
#include <SPI.h> // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h> // UDP library from: bjoern@cs.stanford.edu 12/30/2008
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168,1,177);
unsigned int localPort = 8888; // local port to listen on
// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged"; // a string to send back
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
void setup() {
// start the Ethernet and UDP:
Ethernet.begin(mac,ip);
Udp.begin(localPort);
Serial.begin(9600);
}
void loop() {
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if(packetSize)
{
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remote = Udp.remoteIP();
for (int i =0; i < 4; i++)
{
Serial.print(remote[i], DEC);
if (i < 3)
{
Serial.print(".");
}
}
Serial.print(", port ");
Serial.println(Udp.remotePort());
// read the packet into packetBufffer
Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
Serial.println("Contents:");
Serial.println(packetBuffer);
// send a reply, to the IP address and port that sent us the packet we received
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(ReplyBuffer);
Udp.endPacket();
}
delay(10);
}
/*
Processing sketch to run with this example
=====================================================
// Processing UDP example to send and receive string data from Arduino
// press any key to send the "Hello Arduino" message
import hypermedia.net.*;
UDP udp; // define the UDP object
void setup() {
udp = new UDP( this, 6000 ); // create a new datagram connection on port 6000
//udp.log( true ); // <-- printout the connection activity
udp.listen( true ); // and wait for incoming message
}
void draw()
{
}
void keyPressed() {
String ip = "192.168.1.177"; // the remote IP address
int port = 8888; // the destination port
udp.send("Hello World", ip, port ); // the message to send
}
void receive( byte[] data ) { // <-- default handler
//void receive( byte[] data, String ip, int port ) { // <-- extended handler
for(int i=0; i < data.length; i++)
print(char(data[i]));
println();
}
*/

View File

@@ -1,149 +0,0 @@
/*
Udp NTP Client
Get the time from a Network Time Protocol (NTP) time server
Demonstrates use of UDP sendPacket and ReceivePacket
For more on NTP time servers and the messages needed to communicate with them,
see http://en.wikipedia.org/wiki/Network_Time_Protocol
Warning: NTP Servers are subject to temporary failure or IP address change.
Plese check
http://tf.nist.gov/tf-cgi/servers.cgi
if the time server used in the example didn't work.
created 4 Sep 2010
by Michael Margolis
modified 9 Apr 2012
by Tom Igoe
This code is in the public domain.
*/
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
unsigned int localPort = 8888; // local port to listen for UDP packets
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server
const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start Ethernet and UDP
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
for(;;)
;
}
Udp.begin(localPort);
}
void loop()
{
sendNTPpacket(timeServer); // send an NTP packet to a time server
// wait to see if a reply is available
delay(1000);
if ( Udp.parsePacket() ) {
// We've received a packet, read the data from it
Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer
//the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = " );
Serial.println(secsSince1900);
// now convert NTP time into everyday time:
Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
// print Unix time:
Serial.println(epoch);
// print the hour, minute and second:
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
Serial.print(':');
if ( ((epoch % 3600) / 60) < 10 ) {
// In the first 10 minutes of each hour, we'll want a leading '0'
Serial.print('0');
}
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
Serial.print(':');
if ( (epoch % 60) < 10 ) {
// In the first 10 seconds of each minute, we'll want a leading '0'
Serial.print('0');
}
Serial.println(epoch %60); // print the second
}
// wait ten seconds before asking for the time again
delay(10000);
}
// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress& address)
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer,NTP_PACKET_SIZE);
Udp.endPacket();
}

View File

@@ -1,80 +0,0 @@
/*
Web client
This sketch connects to a website (http://www.google.com)
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
created 18 Dec 2009
modified 9 Apr 2012
by David A. Mellis
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server(173,194,33,104); // Google
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
for(;;)
;
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected");
// Make a HTTP request:
client.println("GET /search?q=arduino HTTP/1.0");
client.println();
}
else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop()
{
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing forevermore:
for(;;)
;
}
}

View File

@@ -1,111 +0,0 @@
/*
Repeating Web client
This sketch connects to a a web server and makes a request
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.
This example uses DNS, by assigning the Ethernet client with a MAC address,
IP address, and DNS address.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
created 19 Apr 2012
by Tom Igoe
http://arduino.cc/en/Tutorial/WebClientRepeating
This code is in the public domain.
*/
#include <SPI.h>
#include <Ethernet.h>
// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(10,0,0,20);
// fill in your Domain Name Server address here:
IPAddress myDns(1,1,1,1);
// initialize the library instance:
EthernetClient client;
char server[] = "www.arduino.cc";
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 60L*1000L; // delay between updates, in milliseconds
// the "L" is needed to use long type numbers
void setup() {
// start serial port:
Serial.begin(9600);
// give the ethernet module time to boot up:
delay(1000);
// start the Ethernet connection using a fixed IP address and DNS server:
Ethernet.begin(mac, ip, myDns);
// print the Ethernet board/shield's IP address:
Serial.print("My IP address: ");
Serial.println(Ethernet.localIP());
}
void loop() {
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
httpRequest();
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
// this method makes a HTTP connection to the server:
void httpRequest() {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting...");
// send the HTTP PUT request:
client.println("GET /latest.txt HTTP/1.1");
client.println("Host: www.arduino.cc");
client.println("User-Agent: arduino-ethernet");
client.println("Connection: close");
client.println();
// note the time that the connection was made:
lastConnectionTime = millis();
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println("disconnecting.");
client.stop();
}
}

View File

@@ -1,101 +0,0 @@
/*
Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,177);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// add a meta refresh tag, so the browser pulls again every 5 seconds:
client.println("<meta http-equiv=\"refresh\" content=\"5\">");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}

View File

@@ -1,37 +0,0 @@
#######################################
# Syntax Coloring Map For Ethernet
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Ethernet KEYWORD1
EthernetClient KEYWORD1
EthernetServer KEYWORD1
IPAddress KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
status KEYWORD2
connect KEYWORD2
write KEYWORD2
available KEYWORD2
read KEYWORD2
peek KEYWORD2
flush KEYWORD2
stop KEYWORD2
connected KEYWORD2
begin KEYWORD2
beginPacket KEYWORD2
endPacket KEYWORD2
parsePacket KEYWORD2
remoteIP KEYWORD2
remotePort KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -1,14 +0,0 @@
#ifndef UTIL_H
#define UTIL_H
#define htons(x) ( ((x)<< 8 & 0xFF00) | \
((x)>> 8 & 0x00FF) )
#define ntohs(x) htons(x)
#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \
((x)<< 8 & 0x00FF0000UL) | \
((x)>> 8 & 0x0000FF00UL) | \
((x)>>24 & 0x000000FFUL) )
#define ntohl(x) htonl(x)
#endif

View File

@@ -1,400 +0,0 @@
#include "w5100.h"
#include "socket.h"
static uint16_t local_port;
/**
* @brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it.
* @return 1 for success else 0.
*/
uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
{
if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE))
{
close(s);
W5100.writeSnMR(s, protocol | flag);
if (port != 0) {
W5100.writeSnPORT(s, port);
}
else {
local_port++; // if don't set the source port, set local_port number.
W5100.writeSnPORT(s, local_port);
}
W5100.execCmdSn(s, Sock_OPEN);
return 1;
}
return 0;
}
/**
* @brief This function close the socket and parameter is "s" which represent the socket number
*/
void close(SOCKET s)
{
W5100.execCmdSn(s, Sock_CLOSE);
W5100.writeSnIR(s, 0xFF);
}
/**
* @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer.
* @return 1 for success else 0.
*/
uint8_t listen(SOCKET s)
{
if (W5100.readSnSR(s) != SnSR::INIT)
return 0;
W5100.execCmdSn(s, Sock_LISTEN);
return 1;
}
/**
* @brief This function established the connection for the channel in Active (client) mode.
* This function waits for the untill the connection is established.
*
* @return 1 for success else 0.
*/
uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port)
{
if
(
((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
(port == 0x00)
)
return 0;
// set destination IP
W5100.writeSnDIPR(s, addr);
W5100.writeSnDPORT(s, port);
W5100.execCmdSn(s, Sock_CONNECT);
return 1;
}
/**
* @brief This function used for disconnect the socket and parameter is "s" which represent the socket number
* @return 1 for success else 0.
*/
void disconnect(SOCKET s)
{
W5100.execCmdSn(s, Sock_DISCON);
}
/**
* @brief This function used to send the data in TCP mode
* @return 1 for success else 0.
*/
uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len)
{
uint8_t status=0;
uint16_t ret=0;
uint16_t freesize=0;
if (len > W5100.SSIZE)
ret = W5100.SSIZE; // check size not to exceed MAX size.
else
ret = len;
// if freebuf is available, start.
do
{
freesize = W5100.getTXFreeSize(s);
status = W5100.readSnSR(s);
if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT))
{
ret = 0;
break;
}
}
while (freesize < ret);
// copy data
W5100.send_data_processing(s, (uint8_t *)buf, ret);
W5100.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
/* m2008.01 [bj] : reduce code */
if ( W5100.readSnSR(s) == SnSR::CLOSED )
{
close(s);
return 0;
}
}
/* +2008.01 bj */
W5100.writeSnIR(s, SnIR::SEND_OK);
return ret;
}
/**
* @brief This function is an application I/F function which is used to receive the data in TCP mode.
* It continues to wait for data as much as the application wants to receive.
*
* @return received data size for success else -1.
*/
int16_t recv(SOCKET s, uint8_t *buf, int16_t len)
{
// Check how much data is available
int16_t ret = W5100.getRXReceivedSize(s);
if ( ret == 0 )
{
// No data available.
uint8_t status = W5100.readSnSR(s);
if ( status == SnSR::LISTEN || status == SnSR::CLOSED || status == SnSR::CLOSE_WAIT )
{
// The remote end has closed its side of the connection, so this is the eof state
ret = 0;
}
else
{
// The connection is still up, but there's no data waiting to be read
ret = -1;
}
}
else if (ret > len)
{
ret = len;
}
if ( ret > 0 )
{
W5100.recv_data_processing(s, buf, ret);
W5100.execCmdSn(s, Sock_RECV);
}
return ret;
}
/**
* @brief Returns the first byte in the receive queue (no checking)
*
* @return
*/
uint16_t peek(SOCKET s, uint8_t *buf)
{
W5100.recv_data_processing(s, buf, 1, 1);
return 1;
}
/**
* @brief This function is an application I/F function which is used to send the data for other then TCP mode.
* Unlike TCP transmission, The peer's destination address and the port is needed.
*
* @return This function return send data size for success else -1.
*/
uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port)
{
uint16_t ret=0;
if (len > W5100.SSIZE) ret = W5100.SSIZE; // check size not to exceed MAX size.
else ret = len;
if
(
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
((port == 0x00)) ||(ret == 0)
)
{
/* +2008.01 [bj] : added return value */
ret = 0;
}
else
{
W5100.writeSnDIPR(s, addr);
W5100.writeSnDPORT(s, port);
// copy data
W5100.send_data_processing(s, (uint8_t *)buf, ret);
W5100.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
if (W5100.readSnIR(s) & SnIR::TIMEOUT)
{
/* +2008.01 [bj]: clear interrupt */
W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */
return 0;
}
}
/* +2008.01 bj */
W5100.writeSnIR(s, SnIR::SEND_OK);
}
return ret;
}
/**
* @brief This function is an application I/F function which is used to receive the data in other then
* TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well.
*
* @return This function return received data size for success else -1.
*/
uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port)
{
uint8_t head[8];
uint16_t data_len=0;
uint16_t ptr=0;
if ( len > 0 )
{
ptr = W5100.readSnRX_RD(s);
switch (W5100.readSnMR(s) & 0x07)
{
case SnMR::UDP :
W5100.read_data(s, ptr, head, 0x08);
ptr += 8;
// read peer's IP address, port number.
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = head[4];
*port = (*port << 8) + head[5];
data_len = head[6];
data_len = (data_len << 8) + head[7];
W5100.read_data(s, ptr, buf, data_len); // data copy.
ptr += data_len;
W5100.writeSnRX_RD(s, ptr);
break;
case SnMR::IPRAW :
W5100.read_data(s, ptr, head, 0x06);
ptr += 6;
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
data_len = head[4];
data_len = (data_len << 8) + head[5];
W5100.read_data(s, ptr, buf, data_len); // data copy.
ptr += data_len;
W5100.writeSnRX_RD(s, ptr);
break;
case SnMR::MACRAW:
W5100.read_data(s, ptr, head, 2);
ptr+=2;
data_len = head[0];
data_len = (data_len<<8) + head[1] - 2;
W5100.read_data(s, ptr, buf, data_len);
ptr += data_len;
W5100.writeSnRX_RD(s, ptr);
break;
default :
break;
}
W5100.execCmdSn(s, Sock_RECV);
}
return data_len;
}
uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
{
uint8_t status=0;
uint16_t ret=0;
if (len > W5100.SSIZE)
ret = W5100.SSIZE; // check size not to exceed MAX size.
else
ret = len;
if (ret == 0)
return 0;
W5100.send_data_processing(s, (uint8_t *)buf, ret);
W5100.execCmdSn(s, Sock_SEND);
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
status = W5100.readSnSR(s);
if (W5100.readSnIR(s) & SnIR::TIMEOUT)
{
/* in case of igmp, if send fails, then socket closed */
/* if you want change, remove this code. */
close(s);
return 0;
}
}
W5100.writeSnIR(s, SnIR::SEND_OK);
return ret;
}
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
{
uint16_t ret =0;
if (len > W5100.getTXFreeSize(s))
{
ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size.
}
else
{
ret = len;
}
W5100.send_data_processing_offset(s, offset, buf, ret);
return ret;
}
int startUDP(SOCKET s, uint8_t* addr, uint16_t port)
{
if
(
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
((port == 0x00))
)
{
return 0;
}
else
{
W5100.writeSnDIPR(s, addr);
W5100.writeSnDPORT(s, port);
return 1;
}
}
int sendUDP(SOCKET s)
{
W5100.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
if (W5100.readSnIR(s) & SnIR::TIMEOUT)
{
/* +2008.01 [bj]: clear interrupt */
W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT));
return 0;
}
}
/* +2008.01 bj */
W5100.writeSnIR(s, SnIR::SEND_OK);
/* Sent ok */
return 1;
}

View File

@@ -1,41 +0,0 @@
#ifndef _SOCKET_H_
#define _SOCKET_H_
#include "w5100.h"
extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode)
extern void close(SOCKET s); // Close socket
extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection)
extern void disconnect(SOCKET s); // disconnect the connection
extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection)
extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP)
extern int16_t recv(SOCKET s, uint8_t * buf, int16_t len); // Receive data (TCP)
extern uint16_t peek(SOCKET s, uint8_t *buf);
extern uint16_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); // Send data (UDP/IP RAW)
extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); // Receive data (UDP/IP RAW)
extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len);
// Functions to allow buffered UDP send (i.e. where the UDP datagram is built up over a
// number of calls before being sent
/*
@brief This function sets up a UDP datagram, the data for which will be provided by one
or more calls to bufferData and then finally sent with sendUDP.
@return 1 if the datagram was successfully set up, or 0 if there was an error
*/
extern int startUDP(SOCKET s, uint8_t* addr, uint16_t port);
/*
@brief This function copies up to len bytes of data from buf into a UDP datagram to be
sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls.
@return Number of bytes successfully buffered
*/
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len);
/*
@brief Send a UDP datagram built up from a sequence of startUDP followed by one or more
calls to bufferData.
@return 1 if the datagram was successfully sent, or 0 if there was an error
*/
int sendUDP(SOCKET s);
#endif
/* _SOCKET_H_ */

View File

@@ -1,183 +0,0 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <string.h>
#include "w5100.h"
// W5100 controller instance
W5100Class W5100;
#define SPI_CS 10
#define TX_RX_MAX_BUF_SIZE 2048
#define TX_BUF 0x1100
#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
#define TXBUF_BASE 0x4000
#define RXBUF_BASE 0x6000
void W5100Class::init(void)
{
delay(300);
SPI.begin(SPI_CS);
// Set clock to 4Mhz (W5100 should support up to about 14Mhz)
SPI.setClockDivider(SPI_CS, 21);
SPI.setDataMode(SPI_CS, SPI_MODE0);
writeMR(1<<RST);
writeTMSR(0x55);
writeRMSR(0x55);
for (int i=0; i<MAX_SOCK_NUM; i++) {
SBASE[i] = TXBUF_BASE + SSIZE * i;
RBASE[i] = RXBUF_BASE + RSIZE * i;
}
}
uint16_t W5100Class::getTXFreeSize(SOCKET s)
{
uint16_t val=0, val1=0;
do {
val1 = readSnTX_FSR(s);
if (val1 != 0)
val = readSnTX_FSR(s);
}
while (val != val1);
return val;
}
uint16_t W5100Class::getRXReceivedSize(SOCKET s)
{
uint16_t val=0,val1=0;
do {
val1 = readSnRX_RSR(s);
if (val1 != 0)
val = readSnRX_RSR(s);
}
while (val != val1);
return val;
}
void W5100Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
{
// This is same as having no offset in a call to send_data_processing_offset
send_data_processing_offset(s, 0, data, len);
}
void W5100Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
{
uint16_t ptr = readSnTX_WR(s);
ptr += data_offset;
uint16_t offset = ptr & SMASK;
uint16_t dstAddr = offset + SBASE[s];
if (offset + len > SSIZE)
{
// Wrap around circular buffer
uint16_t size = SSIZE - offset;
write(dstAddr, data, size);
write(SBASE[s], data + size, len - size);
}
else {
write(dstAddr, data, len);
}
ptr += len;
writeSnTX_WR(s, ptr);
}
void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
{
uint16_t ptr;
ptr = readSnRX_RD(s);
read_data(s, ptr, data, len);
if (!peek)
{
ptr += len;
writeSnRX_RD(s, ptr);
}
}
void W5100Class::read_data(SOCKET s, volatile uint16_t src, volatile uint8_t *dst, uint16_t len)
{
uint16_t size;
uint16_t src_mask;
uint16_t src_ptr;
src_mask = src & RMASK;
src_ptr = RBASE[s] + src_mask;
if( (src_mask + len) > RSIZE )
{
size = RSIZE - src_mask;
read(src_ptr, (uint8_t *)dst, size);
dst += size;
read(RBASE[s], (uint8_t *) dst, len - size);
}
else
read(src_ptr, (uint8_t *) dst, len);
}
uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
{
SPI.transfer(SPI_CS, 0xF0, SPI_CONTINUE);
SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE);
SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE);
SPI.transfer(SPI_CS, _data);
return 1;
}
uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
{
for (uint16_t i=0; i<_len; i++)
{
SPI.transfer(SPI_CS, 0xF0, SPI_CONTINUE);
SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE);
SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE);
SPI.transfer(SPI_CS, _buf[i]);
_addr++;
}
return _len;
}
uint8_t W5100Class::read(uint16_t _addr)
{
SPI.transfer(SPI_CS, 0x0F, SPI_CONTINUE);
SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE);
SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE);
uint8_t _data = SPI.transfer(SPI_CS, 0);
return _data;
}
uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
{
for (uint16_t i=0; i<_len; i++)
{
SPI.transfer(SPI_CS, 0x0F, SPI_CONTINUE);
SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE);
SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE);
_buf[i] = SPI.transfer(SPI_CS, 0);
_addr++;
}
return _len;
}
void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) {
// Send command to socket
writeSnCR(s, _cmd);
// Wait for command to complete
while (readSnCR(s))
;
}

View File

@@ -1,384 +0,0 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#ifndef W5100_H_INCLUDED
#define W5100_H_INCLUDED
#include <SPI.h>
#define MAX_SOCK_NUM 4
typedef uint8_t SOCKET;
#define IDM_OR 0x8000
#define IDM_AR0 0x8001
#define IDM_AR1 0x8002
#define IDM_DR 0x8003
/*
class MR {
public:
static const uint8_t RST = 0x80;
static const uint8_t PB = 0x10;
static const uint8_t PPPOE = 0x08;
static const uint8_t LB = 0x04;
static const uint8_t AI = 0x02;
static const uint8_t IND = 0x01;
};
*/
/*
class IR {
public:
static const uint8_t CONFLICT = 0x80;
static const uint8_t UNREACH = 0x40;
static const uint8_t PPPoE = 0x20;
static const uint8_t SOCK0 = 0x01;
static const uint8_t SOCK1 = 0x02;
static const uint8_t SOCK2 = 0x04;
static const uint8_t SOCK3 = 0x08;
static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); };
};
*/
class SnMR {
public:
static const uint8_t CLOSE = 0x00;
static const uint8_t TCP = 0x01;
static const uint8_t UDP = 0x02;
static const uint8_t IPRAW = 0x03;
static const uint8_t MACRAW = 0x04;
static const uint8_t PPPOE = 0x05;
static const uint8_t ND = 0x20;
static const uint8_t MULTI = 0x80;
};
enum SockCMD {
Sock_OPEN = 0x01,
Sock_LISTEN = 0x02,
Sock_CONNECT = 0x04,
Sock_DISCON = 0x08,
Sock_CLOSE = 0x10,
Sock_SEND = 0x20,
Sock_SEND_MAC = 0x21,
Sock_SEND_KEEP = 0x22,
Sock_RECV = 0x40
};
/*class SnCmd {
public:
static const uint8_t OPEN = 0x01;
static const uint8_t LISTEN = 0x02;
static const uint8_t CONNECT = 0x04;
static const uint8_t DISCON = 0x08;
static const uint8_t CLOSE = 0x10;
static const uint8_t SEND = 0x20;
static const uint8_t SEND_MAC = 0x21;
static const uint8_t SEND_KEEP = 0x22;
static const uint8_t RECV = 0x40;
};
*/
class SnIR {
public:
static const uint8_t SEND_OK = 0x10;
static const uint8_t TIMEOUT = 0x08;
static const uint8_t RECV = 0x04;
static const uint8_t DISCON = 0x02;
static const uint8_t CON = 0x01;
};
class SnSR {
public:
static const uint8_t CLOSED = 0x00;
static const uint8_t INIT = 0x13;
static const uint8_t LISTEN = 0x14;
static const uint8_t SYNSENT = 0x15;
static const uint8_t SYNRECV = 0x16;
static const uint8_t ESTABLISHED = 0x17;
static const uint8_t FIN_WAIT = 0x18;
static const uint8_t CLOSING = 0x1A;
static const uint8_t TIME_WAIT = 0x1B;
static const uint8_t CLOSE_WAIT = 0x1C;
static const uint8_t LAST_ACK = 0x1D;
static const uint8_t UDP = 0x22;
static const uint8_t IPRAW = 0x32;
static const uint8_t MACRAW = 0x42;
static const uint8_t PPPOE = 0x5F;
};
class IPPROTO {
public:
static const uint8_t IP = 0;
static const uint8_t ICMP = 1;
static const uint8_t IGMP = 2;
static const uint8_t GGP = 3;
static const uint8_t TCP = 6;
static const uint8_t PUP = 12;
static const uint8_t UDP = 17;
static const uint8_t IDP = 22;
static const uint8_t ND = 77;
static const uint8_t RAW = 255;
};
class W5100Class {
public:
void init();
/**
* @brief This function is being used for copy the data form Receive buffer of the chip to application buffer.
*
* It calculate the actual physical address where one has to read
* the data from Receive buffer. Here also take care of the condition while it exceed
* the Rx memory uper-bound of socket.
*/
void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len);
/**
* @brief This function is being called by send() and sendto() function also.
*
* This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
* register. User should read upper byte first and lower byte later to get proper value.
*/
void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len);
/**
* @brief A copy of send_data_processing that uses the provided ptr for the
* write offset. Only needed for the "streaming" UDP API, where
* a single UDP packet is built up over a number of calls to
* send_data_processing_ptr, because TX_WR doesn't seem to get updated
* correctly in those scenarios
* @param ptr value to use in place of TX_WR. If 0, then the value is read
* in from TX_WR
* @return New value for ptr, to be used in the next call
*/
// FIXME Update documentation
void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len);
/**
* @brief This function is being called by recv() also.
*
* This function read the Rx read pointer register
* and after copy the data from receive buffer update the Rx write pointer register.
* User should read upper byte first and lower byte later to get proper value.
*/
void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0);
inline void setGatewayIp(uint8_t *_addr);
inline void getGatewayIp(uint8_t *_addr);
inline void setSubnetMask(uint8_t *_addr);
inline void getSubnetMask(uint8_t *_addr);
inline void setMACAddress(uint8_t * addr);
inline void getMACAddress(uint8_t * addr);
inline void setIPAddress(uint8_t * addr);
inline void getIPAddress(uint8_t * addr);
inline void setRetransmissionTime(uint16_t timeout);
inline void setRetransmissionCount(uint8_t _retry);
void execCmdSn(SOCKET s, SockCMD _cmd);
uint16_t getTXFreeSize(SOCKET s);
uint16_t getRXReceivedSize(SOCKET s);
// W5100 Registers
// ---------------
private:
static uint8_t write(uint16_t _addr, uint8_t _data);
static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len);
static uint8_t read(uint16_t addr);
static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len);
#define __GP_REGISTER8(name, address) \
static inline void write##name(uint8_t _data) { \
write(address, _data); \
} \
static inline uint8_t read##name() { \
return read(address); \
}
#define __GP_REGISTER16(name, address) \
static void write##name(uint16_t _data) { \
write(address, _data >> 8); \
write(address+1, _data & 0xFF); \
} \
static uint16_t read##name() { \
uint16_t res = read(address); \
res = (res << 8) + read(address + 1); \
return res; \
}
#define __GP_REGISTER_N(name, address, size) \
static uint16_t write##name(uint8_t *_buff) { \
return write(address, _buff, size); \
} \
static uint16_t read##name(uint8_t *_buff) { \
return read(address, _buff, size); \
}
public:
__GP_REGISTER8 (MR, 0x0000); // Mode
__GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address
__GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address
__GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address
__GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address
__GP_REGISTER8 (IR, 0x0015); // Interrupt
__GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask
__GP_REGISTER16(RTR, 0x0017); // Timeout address
__GP_REGISTER8 (RCR, 0x0019); // Retry count
__GP_REGISTER8 (RMSR, 0x001A); // Receive memory size
__GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size
__GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode
__GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer
__GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number
__GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode
__GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode
#undef __GP_REGISTER8
#undef __GP_REGISTER16
#undef __GP_REGISTER_N
// W5100 Socket registers
// ----------------------
private:
static inline uint8_t readSn(SOCKET _s, uint16_t _addr);
static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data);
static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
static const uint16_t CH_BASE = 0x0400;
static const uint16_t CH_SIZE = 0x0100;
#define __SOCKET_REGISTER8(name, address) \
static inline void write##name(SOCKET _s, uint8_t _data) { \
writeSn(_s, address, _data); \
} \
static inline uint8_t read##name(SOCKET _s) { \
return readSn(_s, address); \
}
#define __SOCKET_REGISTER16(name, address) \
static void write##name(SOCKET _s, uint16_t _data) { \
writeSn(_s, address, _data >> 8); \
writeSn(_s, address+1, _data & 0xFF); \
} \
static uint16_t read##name(SOCKET _s) { \
uint16_t res = readSn(_s, address); \
uint16_t res2 = readSn(_s,address + 1); \
res = res << 8; \
res2 = res2 & 0xFF; \
res = res | res2; \
return res; \
}
#define __SOCKET_REGISTER_N(name, address, size) \
static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \
return writeSn(_s, address, _buff, size); \
} \
static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \
return readSn(_s, address, _buff, size); \
}
public:
__SOCKET_REGISTER8(SnMR, 0x0000) // Mode
__SOCKET_REGISTER8(SnCR, 0x0001) // Command
__SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt
__SOCKET_REGISTER8(SnSR, 0x0003) // Status
__SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port
__SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr
__SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr
__SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port
__SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size
__SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode
__SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS
__SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL
__SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size
__SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer
__SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer
__SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size
__SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer
__SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?)
#undef __SOCKET_REGISTER8
#undef __SOCKET_REGISTER16
#undef __SOCKET_REGISTER_N
private:
static const uint8_t RST = 7; // Reset BIT
static const int SOCKETS = 4;
static const uint16_t SMASK = 0x07FF; // Tx buffer MASK
static const uint16_t RMASK = 0x07FF; // Rx buffer MASK
public:
static const uint16_t SSIZE = 2048; // Max Tx buffer size
private:
static const uint16_t RSIZE = 2048; // Max Rx buffer size
uint16_t SBASE[SOCKETS]; // Tx buffer base address
uint16_t RBASE[SOCKETS]; // Rx buffer base address
};
extern W5100Class W5100;
uint8_t W5100Class::readSn(SOCKET _s, uint16_t _addr) {
return read(CH_BASE + _s * CH_SIZE + _addr);
}
uint8_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) {
return write(CH_BASE + _s * CH_SIZE + _addr, _data);
}
uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) {
return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
}
uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) {
return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
}
void W5100Class::getGatewayIp(uint8_t *_addr) {
readGAR(_addr);
}
void W5100Class::setGatewayIp(uint8_t *_addr) {
writeGAR(_addr);
}
void W5100Class::getSubnetMask(uint8_t *_addr) {
readSUBR(_addr);
}
void W5100Class::setSubnetMask(uint8_t *_addr) {
writeSUBR(_addr);
}
void W5100Class::getMACAddress(uint8_t *_addr) {
readSHAR(_addr);
}
void W5100Class::setMACAddress(uint8_t *_addr) {
writeSHAR(_addr);
}
void W5100Class::getIPAddress(uint8_t *_addr) {
readSIPR(_addr);
}
void W5100Class::setIPAddress(uint8_t *_addr) {
writeSIPR(_addr);
}
void W5100Class::setRetransmissionTime(uint16_t _timeout) {
writeRTR(_timeout);
}
void W5100Class::setRetransmissionCount(uint8_t _retry) {
writeRCR(_retry);
}
#endif

View File

@@ -1,129 +0,0 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
* SPI Master library for arduino.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#include "SPI.h"
SPIClass::SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)) :
spi(_spi), id(_id), initCb(_initCb)
{
// Empty
}
void SPIClass::begin() {
initCb();
SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
SPI_Enable(spi);
// NPCS control is left to the user
// Default speed set to 4Mhz
setClockDivider(BOARD_SPI_DEFAULT_SS, 21);
setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0);
setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST);
}
void SPIClass::begin(uint8_t _pin) {
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
PIO_Configure(
g_APinDescription[spiPin].pPort,
g_APinDescription[spiPin].ulPinType,
g_APinDescription[spiPin].ulPin,
g_APinDescription[spiPin].ulPinConfiguration);
// Default speed set to 4Mhz
setClockDivider(_pin, 21);
setDataMode(_pin, SPI_MODE0);
setBitOrder(_pin, MSBFIRST);
}
void SPIClass::end(uint8_t _pin) {
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
// Setting the pin as INPUT will disconnect it from SPI peripheral
pinMode(spiPin, INPUT);
}
void SPIClass::end() {
SPI_Disable(spi);
}
void SPIClass::setBitOrder(uint8_t _pin, BitOrder _bitOrder) {
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
bitOrder[ch] = _bitOrder;
}
void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode) {
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
mode[ch] = _mode | SPI_CSR_CSAAT;
// SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed
// transfer. Some device needs that for working properly.
SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1));
}
void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider) {
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
divider[ch] = _divider;
// SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed
// transfer. Some device needs that for working properly.
SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1));
}
byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
// Reverse bit order
if (bitOrder[ch] == LSBFIRST)
_data = __REV(__RBIT(_data));
uint32_t d = _data | SPI_PCS(ch);
if (_mode == SPI_LAST)
d |= SPI_TDR_LASTXFER;
// SPI_Write(spi, _channel, _data);
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
;
spi->SPI_TDR = d;
// return SPI_Read(spi);
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
;
d = spi->SPI_RDR;
// Reverse bit order
if (bitOrder[ch] == LSBFIRST)
d = __REV(__RBIT(d));
return d & 0xFF;
}
void SPIClass::attachInterrupt(void) {
// Should be enableInterrupt()
}
void SPIClass::detachInterrupt(void) {
// Should be disableInterrupt()
}
#if SPI_INTERFACES_COUNT > 0
static void SPI_0_Init(void) {
PIO_Configure(
g_APinDescription[PIN_SPI_MOSI].pPort,
g_APinDescription[PIN_SPI_MOSI].ulPinType,
g_APinDescription[PIN_SPI_MOSI].ulPin,
g_APinDescription[PIN_SPI_MOSI].ulPinConfiguration);
PIO_Configure(
g_APinDescription[PIN_SPI_MISO].pPort,
g_APinDescription[PIN_SPI_MISO].ulPinType,
g_APinDescription[PIN_SPI_MISO].ulPin,
g_APinDescription[PIN_SPI_MISO].ulPinConfiguration);
PIO_Configure(
g_APinDescription[PIN_SPI_SCK].pPort,
g_APinDescription[PIN_SPI_SCK].ulPinType,
g_APinDescription[PIN_SPI_SCK].ulPin,
g_APinDescription[PIN_SPI_SCK].ulPinConfiguration);
}
SPIClass SPI(SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
#endif

View File

@@ -1,69 +0,0 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
* SPI Master library for arduino.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#ifndef _SPI_H_INCLUDED
#define _SPI_H_INCLUDED
#include "variant.h"
#include <stdio.h>
#define SPI_MODE0 0x02
#define SPI_MODE1 0x00
#define SPI_MODE2 0x03
#define SPI_MODE3 0x01
enum SPITransferMode {
SPI_CONTINUE,
SPI_LAST
};
class SPIClass {
public:
SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void));
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST) { return transfer(BOARD_SPI_DEFAULT_SS, _data, _mode); }
byte transfer(byte _channel, uint8_t _data, SPITransferMode _mode = SPI_LAST);
// SPI Configuration methods
void attachInterrupt(void);
void detachInterrupt(void);
void begin(void);
void end(void);
// Attach/Detach pin to/from SPI controller
void begin(uint8_t _pin);
void end(uint8_t _pin);
// These methods sets a parameter on a single pin
void setBitOrder(uint8_t _pin, BitOrder);
void setDataMode(uint8_t _pin, uint8_t);
void setClockDivider(uint8_t _pin, uint8_t);
// These methods sets the same parameters but on default pin BOARD_SPI_DEFAULT_SS
void setBitOrder(BitOrder _order) { setBitOrder(BOARD_SPI_DEFAULT_SS, _order); };
void setDataMode(uint8_t _mode) { setDataMode(BOARD_SPI_DEFAULT_SS, _mode); };
void setClockDivider(uint8_t _div) { setClockDivider(BOARD_SPI_DEFAULT_SS, _div); };
private:
Spi *spi;
uint32_t id;
BitOrder bitOrder[SPI_CHANNELS_NUM];
uint32_t divider[SPI_CHANNELS_NUM];
uint32_t mode[SPI_CHANNELS_NUM];
void (*initCb)(void);
};
#if SPI_INTERFACES_COUNT > 0
extern SPIClass SPI;
#endif
#endif

View File

@@ -1,143 +0,0 @@
/*
SCP1000 Barometric Pressure Sensor Display
Shows the output of a Barometric Pressure Sensor on a
Uses the SPI library. For details on the sensor, see:
http://www.sparkfun.com/commerce/product_info.php?products_id=8161
http://www.vti.fi/en/support/obsolete_products/pressure_sensors/
This sketch adapted from Nathan Seidle's SCP1000 example for PIC:
http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip
Circuit:
SCP1000 sensor attached to pins 6, 7, 10 - 13:
DRDY: pin 6
CSB: pin 7
MOSI: pin 11
MISO: pin 12
SCK: pin 13
created 31 July 2010
modified 14 August 2010
by Tom Igoe
*/
// the sensor communicates using SPI, so include the library:
#include <SPI.h>
//Sensor's memory register addresses:
const int PRESSURE = 0x1F; //3 most significant bits of pressure
const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure
const int TEMPERATURE = 0x21; //16 bit temperature reading
const byte READ = 0b11111100; // SCP1000's read command
const byte WRITE = 0b00000010; // SCP1000's write command
// pins used for the connection with the sensor
// the other you need are controlled by the SPI library):
const int dataReadyPin = 6;
const int chipSelectPin = 7;
void setup() {
Serial.begin(9600);
// start the SPI library:
SPI.begin();
// initalize the data ready and chip select pins:
pinMode(dataReadyPin, INPUT);
pinMode(chipSelectPin, OUTPUT);
//Configure SCP1000 for low noise configuration:
writeRegister(0x02, 0x2D);
writeRegister(0x01, 0x03);
writeRegister(0x03, 0x02);
// give the sensor time to set up:
delay(100);
}
void loop() {
//Select High Resolution Mode
writeRegister(0x03, 0x0A);
// don't do anything until the data ready pin is high:
if (digitalRead(dataReadyPin) == HIGH) {
//Read the temperature data
int tempData = readRegister(0x21, 2);
// convert the temperature to celsius and display it:
float realTemp = (float)tempData / 20.0;
Serial.print("Temp[C]=");
Serial.print(realTemp);
//Read the pressure data highest 3 bits:
byte pressure_data_high = readRegister(0x1F, 1);
pressure_data_high &= 0b00000111; //you only needs bits 2 to 0
//Read the pressure data lower 16 bits:
unsigned int pressure_data_low = readRegister(0x20, 2);
//combine the two parts into one 19-bit number:
long pressure = ((pressure_data_high << 16) | pressure_data_low)/4;
// display the temperature:
Serial.println("\tPressure [Pa]=" + String(pressure));
}
}
//Read from or write to register from the SCP1000:
unsigned int readRegister(byte thisRegister, int bytesToRead ) {
byte inByte = 0; // incoming byte from the SPI
unsigned int result = 0; // result to return
Serial.print(thisRegister, BIN);
Serial.print("\t");
// SCP1000 expects the register name in the upper 6 bits
// of the byte. So shift the bits left by two bits:
thisRegister = thisRegister << 2;
// now combine the address and the command into one byte
byte dataToSend = thisRegister & READ;
Serial.println(thisRegister, BIN);
// take the chip select low to select the device:
digitalWrite(chipSelectPin, LOW);
// send the device the register you want to read:
SPI.transfer(dataToSend);
// send a value of 0 to read the first byte returned:
result = SPI.transfer(0x00);
// decrement the number of bytes left to read:
bytesToRead--;
// if you still have another byte to read:
if (bytesToRead > 0) {
// shift the first byte left, then get the second byte:
result = result << 8;
inByte = SPI.transfer(0x00);
// combine the byte you just got with the previous one:
result = result | inByte;
// decrement the number of bytes left to read:
bytesToRead--;
}
// take the chip select high to de-select:
digitalWrite(chipSelectPin, HIGH);
// return the result:
return(result);
}
//Sends a write command to SCP1000
void writeRegister(byte thisRegister, byte thisValue) {
// SCP1000 expects the register address in the upper 6 bits
// of the byte. So shift the bits left by two bits:
thisRegister = thisRegister << 2;
// now combine the register address and the command into one byte:
byte dataToSend = thisRegister | WRITE;
// take the chip select low to select the device:
digitalWrite(chipSelectPin, LOW);
SPI.transfer(dataToSend); //Send register location
SPI.transfer(thisValue); //Send value to record into register
// take the chip select high to de-select:
digitalWrite(chipSelectPin, HIGH);
}

View File

@@ -1,71 +0,0 @@
/*
Digital Pot Control
This example controls an Analog Devices AD5206 digital potentiometer.
The AD5206 has 6 potentiometer channels. Each channel's pins are labeled
A - connect this to voltage
W - this is the pot's wiper, which changes when you set it
B - connect this to ground.
The AD5206 is SPI-compatible,and to command it, you send two bytes,
one with the channel number (0 - 5) and one with the resistance value for the
channel (0 - 255).
The circuit:
* All A pins of AD5206 connected to +5V
* All B pins of AD5206 connected to ground
* An LED and a 220-ohm resisor in series connected from each W pin to ground
* CS - to digital pin 10 (SS pin)
* SDI - to digital pin 11 (MOSI pin)
* CLK - to digital pin 13 (SCK pin)
created 10 Aug 2010
by Tom Igoe
Thanks to Heather Dewey-Hagborg for the original tutorial, 2005
*/
// inslude the SPI library:
#include <SPI.h>
// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;
void setup() {
// set the slaveSelectPin as an output:
pinMode (slaveSelectPin, OUTPUT);
// initialize SPI:
SPI.begin();
}
void loop() {
// go through the six channels of the digital pot:
for (int channel = 0; channel < 6; channel++) {
// change the resistance on this channel from min to max:
for (int level = 0; level < 255; level++) {
digitalPotWrite(channel, level);
delay(10);
}
// wait a second at the top:
delay(100);
// change the resistance on this channel from max to min:
for (int level = 0; level < 255; level++) {
digitalPotWrite(channel, 255 - level);
delay(10);
}
}
}
int digitalPotWrite(int address, int value) {
// take the SS pin low to select the chip:
digitalWrite(slaveSelectPin,LOW);
// send in the address and value via SPI:
SPI.transfer(address);
SPI.transfer(value);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin,HIGH);
}

View File

@@ -1,31 +0,0 @@
#######################################
# Syntax Coloring Map SPI
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
SPI KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
transfer KEYWORD2
#setBitOrder KEYWORD2
setDataMode KEYWORD2
setClockDivider KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
SPI_MODE0 LITERAL1
SPI_MODE1 LITERAL1
SPI_MODE2 LITERAL1
SPI_MODE3 LITERAL1
SPI_CONTINUE LITERAL1
SPI_LAST LITERAL1

View File

@@ -1,155 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Scheduler.h"
extern "C" {
#define NUM_REGS 10 // r4-r11, sp, pc
typedef struct CoopTask {
uint32_t regs[NUM_REGS];
void* stackPtr;
struct CoopTask* next;
struct CoopTask* prev;
} CoopTask;
static CoopTask *cur = 0;
static CoopTask* __attribute__((noinline)) coopSchedule(char taskDied) {
CoopTask* next = cur->next;
if (taskDied) {
// Halt if last task died.
if (next == cur)
while (1)
;
// Delete task
if (cur->stackPtr)
free(cur->stackPtr);
cur->next->prev = cur->prev;
cur->prev->next = cur->next;
free(cur);
}
cur = next;
return next;
}
static void __attribute__((naked)) __attribute__((noinline)) coopTaskStart(void) {
asm (
"mov r0, r5;"
"blx r4;"
"mov r0, #1;"
"bl coopSchedule;"
"ldmia r0, {r4-r12, lr};"
"mov sp, r12;"
"bx lr;"
);
}
static void __attribute__((naked)) __attribute__((noinline)) coopDoYield(CoopTask* curTask) {
asm (
"mov r12, sp;"
"stmia r0, {r4-r12, lr};"
"mov r0, #0;"
"bl coopSchedule;"
"ldmia r0, {r4-r12, lr};"
"mov sp, r12;"
"bx lr;"
);
}
static int coopInit(void) {
CoopTask* task;
task = reinterpret_cast<CoopTask *>(malloc(sizeof(CoopTask)));
if (!task)
return 0;
task->next = task;
task->prev = task;
task->stackPtr = 0;
cur = task;
return 1;
}
static int coopSpawn(SchedulerParametricTask taskF, void* taskData, uint32_t stackSz) {
uint8_t *stack = (uint8_t*)malloc(stackSz);
if (!stack)
return 0;
CoopTask *task = reinterpret_cast<CoopTask *>(malloc(sizeof(CoopTask)));
if (!task) {
free(stack);
return 0;
}
task->stackPtr = stack;
task->regs[0] = (uint32_t) taskF;
task->regs[1] = (uint32_t) taskData;
task->regs[8] = ((uint32_t)(stack + stackSz)) & ~7;
task->regs[9] = (uint32_t) & coopTaskStart;
task->prev = cur;
task->next = cur->next;
cur->next->prev = task;
cur->next = task;
// These are here so compiler is sure that function is
// referenced in both variants (cancels a warning)
if (stackSz == 0xFFFFFFFF)
coopSchedule(0);
if (stackSz == 0xFFFFFFFE)
coopSchedule(1);
return 1;
}
void yield(void) {
coopDoYield(cur);
}
}; // extern "C"
SchedulerClass::SchedulerClass() {
coopInit();
}
static void startLoopHelper(void *taskData) {
SchedulerTask task = reinterpret_cast<SchedulerTask>(taskData);
while (true)
task();
}
void SchedulerClass::startLoop(SchedulerTask task, uint32_t stackSize) {
coopSpawn(startLoopHelper, reinterpret_cast<void *>(task), stackSize);
}
static void startTaskHelper(void *taskData) {
SchedulerTask task = reinterpret_cast<SchedulerTask>(taskData);
task();
}
void SchedulerClass::start(SchedulerTask task, uint32_t stackSize) {
coopSpawn(startTaskHelper, reinterpret_cast<void *>(task), stackSize);
}
void SchedulerClass::start(SchedulerParametricTask task, void *taskData, uint32_t stackSize) {
coopSpawn(task, taskData, stackSize);
}
SchedulerClass Scheduler;

View File

@@ -1,40 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _SCHEDULDER_H_
#define _SCHEDULDER_H_
#include <Arduino.h>
extern "C" {
typedef void (*SchedulerTask)(void);
typedef void (*SchedulerParametricTask)(void *);
}
class SchedulerClass {
public:
SchedulerClass();
static void startLoop(SchedulerTask task, uint32_t stackSize = 1024);
static void start(SchedulerTask task, uint32_t stackSize = 1024);
static void start(SchedulerParametricTask task, void *data, uint32_t stackSize = 1024);
static void yield() { ::yield(); };
};
extern SchedulerClass Scheduler;
#endif

View File

@@ -1,81 +0,0 @@
/*
Multiple Blinks
Demonstrates the use of the Scheduler library for the Arduino Due
Hardware required :
* LEDs connected to pins 11, 12, and 13
created 8 Oct 2012
by Cristian Maglie
Modified by
Scott Fitzgerald 19 Oct 2012
This example code is in the public domain
http://arduino.cc/en/Tutorial/MultipleBlinks
*/
// Include Scheduler since we want to manage multiple tasks.
#include <Scheduler.h>
int led1 = 13;
int led2 = 12;
int led3 = 11;
void setup() {
Serial.begin(9600);
// Setup the 3 pins as OUTPUT
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
// Add "loop2" and "loop3" to scheduling.
// "loop" is always started by default.
Scheduler.startLoop(loop2);
Scheduler.startLoop(loop3);
}
// Task no.1: blink LED with 1 second delay.
void loop() {
digitalWrite(led1, HIGH);
// IMPORTANT:
// When multiple tasks are running 'delay' passes control to
// other tasks while waiting and guarantees they get executed.
delay(1000);
digitalWrite(led1, LOW);
delay(1000);
}
// Task no.2: blink LED with 0.1 second delay.
void loop2() {
digitalWrite(led2, HIGH);
delay(100);
digitalWrite(led2, LOW);
delay(100);
}
// Task no.3: accept commands from Serial port
// '0' turns off LED
// '1' turns on LED
void loop3() {
if (Serial.available()) {
char c = Serial.read();
if (c=='0') {
digitalWrite(led3, LOW);
Serial.println("Led turned off!");
}
if (c=='1') {
digitalWrite(led3, HIGH);
Serial.println("Led turned on!");
}
}
// IMPORTANT:
// We must call 'yield' at a regular basis to pass
// control to other tasks.
yield();
}

View File

@@ -1,20 +0,0 @@
#######################################
# Syntax Coloring Map For Scheduler
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Scheduler KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
startLoop KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -1,310 +0,0 @@
/*
Servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
Copyright (c) 2009 Michael Margolis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
The servos are pulsed in the background using the value most recently written using the write() method
Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
The methods are:
Servo - Class for manipulating servo motors connected to Arduino pins.
attach(pin ) - Attaches a servo motor to an i/o pin.
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
default min is 544, max is 2400
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
writeMicroseconds() - Sets the servo pulse width in microseconds
read() - Gets the last written servo pulse width as an angle between 0 and 180.
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached() - Returns true if there is a servo attached.
detach() - Stops an attached servos from pulsing its i/o pin.
*/
#include <Arduino.h>
#include "Servo.h"
#define usToTicks(_us) (( clockCyclesPerMicrosecond() * _us) / 32) // converts microseconds to tick
#define ticksToUs(_ticks) (( (unsigned)_ticks * 32)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
static servo_t servos[MAX_SERVOS]; // static array of servo structures
uint8_t ServoCount = 0; // the total number of attached servos
static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
// convenience macros
#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer
#define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel
#define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo
#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo
/************ static functions common to all instances ***********************/
//timer16_Sequence_t timer;
//------------------------------------------------------------------------------
/// Interrupt handler for the TC0 channel 1.
//------------------------------------------------------------------------------
void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
#if defined (_useTimer1)
void HANDLER_FOR_TIMER1(void) {
Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
}
#endif
#if defined (_useTimer2)
void HANDLER_FOR_TIMER2(void) {
Servo_Handler(_timer2, TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
}
#endif
#if defined (_useTimer3)
void HANDLER_FOR_TIMER3(void) {
Servo_Handler(_timer3, TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
}
#endif
#if defined (_useTimer4)
void HANDLER_FOR_TIMER4(void) {
Servo_Handler(_timer4, TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
}
#endif
#if defined (_useTimer5)
void HANDLER_FOR_TIMER5(void) {
Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
}
#endif
void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel)
{
// clear interrupt
tc->TC_CHANNEL[channel].TC_SR;
if (Channel[timer] < 0) {
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
} else {
if (SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true) {
digitalWrite(SERVO(timer,Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
}
}
Channel[timer]++; // increment to the next channel
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
if(SERVO(timer,Channel[timer]).Pin.isActive == true) { // check if activated
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
}
}
else {
// finished all channels so wait for the refresh period to expire before starting over
if( (tc->TC_CHANNEL[channel].TC_CV) + 4 < usToTicks(REFRESH_INTERVAL) ) { // allow a few ticks to ensure the next OCR1A not missed
tc->TC_CHANNEL[channel].TC_RA = (unsigned int)usToTicks(REFRESH_INTERVAL);
}
else {
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + 4; // at least REFRESH_INTERVAL has elapsed
}
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
}
}
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn)
{
pmc_enable_periph_clk(id);
TC_Configure(tc, channel,
TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
TC_CMR_WAVE | // Waveform mode
TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC
/* 84MHz, MCK/32, for 1.5ms: 3937 */
TC_SetRA(tc, channel, 2625); // 1ms
/* Configure and enable interrupt */
NVIC_EnableIRQ(irqn);
// TC_IER_CPAS: RA Compare
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
// Enables the timer clock and performs a software reset to start the counting
TC_Start(tc, channel);
}
static void initISR(timer16_Sequence_t timer)
{
#if defined (_useTimer1)
if (timer == _timer1)
_initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
#endif
#if defined (_useTimer2)
if (timer == _timer2)
_initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
#endif
#if defined (_useTimer3)
if (timer == _timer3)
_initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
#endif
#if defined (_useTimer4)
if (timer == _timer4)
_initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
#endif
#if defined (_useTimer5)
if (timer == _timer5)
_initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
#endif
}
static void finISR(timer16_Sequence_t timer)
{
#if defined (_useTimer1)
TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
#endif
#if defined (_useTimer2)
TC_Stop(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
#endif
#if defined (_useTimer3)
TC_Stop(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
#endif
#if defined (_useTimer4)
TC_Stop(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
#endif
#if defined (_useTimer5)
TC_Stop(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
#endif
}
static boolean isTimerActive(timer16_Sequence_t timer)
{
// returns true if any servo is active on this timer
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
if(SERVO(timer,channel).Pin.isActive == true)
return true;
}
return false;
}
/****************** end of static functions ******************************/
Servo::Servo()
{
if (ServoCount < MAX_SERVOS) {
this->servoIndex = ServoCount++; // assign a servo index to this instance
servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values
} else {
this->servoIndex = INVALID_SERVO; // too many servos
}
}
uint8_t Servo::attach(int pin)
{
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
}
uint8_t Servo::attach(int pin, int min, int max)
{
timer16_Sequence_t timer;
if (this->servoIndex < MAX_SERVOS) {
pinMode(pin, OUTPUT); // set servo pin to output
servos[this->servoIndex].Pin.nbr = pin;
// todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
this->max = (MAX_PULSE_WIDTH - max)/4;
// initialize the timer if it has not already been initialized
timer = SERVO_INDEX_TO_TIMER(servoIndex);
if (isTimerActive(timer) == false) {
initISR(timer);
}
servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
}
return this->servoIndex;
}
void Servo::detach()
{
timer16_Sequence_t timer;
servos[this->servoIndex].Pin.isActive = false;
timer = SERVO_INDEX_TO_TIMER(servoIndex);
if(isTimerActive(timer) == false) {
finISR(timer);
}
}
void Servo::write(int value)
{
// treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
if (value < MIN_PULSE_WIDTH)
{
if (value < 0)
value = 0;
else if (value > 180)
value = 180;
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
}
writeMicroseconds(value);
}
void Servo::writeMicroseconds(int value)
{
// calculate and store the values for the given channel
byte channel = this->servoIndex;
if( (channel < MAX_SERVOS) ) // ensure channel is valid
{
if (value < SERVO_MIN()) // ensure pulse width is valid
value = SERVO_MIN();
else if (value > SERVO_MAX())
value = SERVO_MAX();
value = value - TRIM_DURATION;
value = usToTicks(value); // convert to ticks after compensating for interrupt overhead
servos[channel].ticks = value;
}
}
int Servo::read() // return the value as degrees
{
return map(readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
}
int Servo::readMicroseconds()
{
unsigned int pulsewidth;
if (this->servoIndex != INVALID_SERVO)
pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION;
else
pulsewidth = 0;
return pulsewidth;
}
bool Servo::attached()
{
return servos[this->servoIndex].Pin.isActive;
}

View File

@@ -1,155 +0,0 @@
/*
Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
Copyright (c) 2009 Michael Margolis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
The servos are pulsed in the background using the value most recently written using the write() method
Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
The sequence used to sieze timers is defined in timers.h
The methods are:
Servo - Class for manipulating servo motors connected to Arduino pins.
attach(pin ) - Attaches a servo motor to an i/o pin.
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
default min is 544, max is 2400
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
writeMicroseconds() - Sets the servo pulse width in microseconds
read() - Gets the last written servo pulse width as an angle between 0 and 180.
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached() - Returns true if there is a servo attached.
detach() - Stops an attached servos from pulsing its i/o pin.
*/
#ifndef Servo_h
#define Servo_h
#include <inttypes.h>
/*
* Defines for 16 bit timers used with Servo library
*
* If _useTimerX is defined then TimerX is a 16 bit timer on the current board
* timer16_Sequence_t enumerates the sequence that the timers should be allocated
* _Nbr_16timers indicates how many 16 bit timers are available.
*/
// For SAM3X:
#define _useTimer1
#define _useTimer2
#define _useTimer3
#define _useTimer4
#define _useTimer5
/*
TC0, chan 0 => TC0_Handler
TC0, chan 1 => TC1_Handler
TC0, chan 2 => TC2_Handler
TC1, chan 0 => TC3_Handler
TC1, chan 1 => TC4_Handler
TC1, chan 2 => TC5_Handler
TC2, chan 0 => TC6_Handler
TC2, chan 1 => TC7_Handler
TC2, chan 2 => TC8_Handler
*/
#if defined (_useTimer1)
#define TC_FOR_TIMER1 TC1
#define CHANNEL_FOR_TIMER1 0
#define ID_TC_FOR_TIMER1 ID_TC3
#define IRQn_FOR_TIMER1 TC3_IRQn
#define HANDLER_FOR_TIMER1 TC3_Handler
#endif
#if defined (_useTimer2)
#define TC_FOR_TIMER2 TC1
#define CHANNEL_FOR_TIMER2 1
#define ID_TC_FOR_TIMER2 ID_TC4
#define IRQn_FOR_TIMER2 TC4_IRQn
#define HANDLER_FOR_TIMER2 TC4_Handler
#endif
#if defined (_useTimer3)
#define TC_FOR_TIMER3 TC1
#define CHANNEL_FOR_TIMER3 2
#define ID_TC_FOR_TIMER3 ID_TC5
#define IRQn_FOR_TIMER3 TC5_IRQn
#define HANDLER_FOR_TIMER3 TC5_Handler
#endif
#if defined (_useTimer4)
#define TC_FOR_TIMER4 TC0
#define CHANNEL_FOR_TIMER4 2
#define ID_TC_FOR_TIMER4 ID_TC2
#define IRQn_FOR_TIMER4 TC2_IRQn
#define HANDLER_FOR_TIMER4 TC2_Handler
#endif
#if defined (_useTimer5)
#define TC_FOR_TIMER5 TC0
#define CHANNEL_FOR_TIMER5 0
#define ID_TC_FOR_TIMER5 ID_TC0
#define IRQn_FOR_TIMER5 TC0_IRQn
#define HANDLER_FOR_TIMER5 TC0_Handler
#endif
typedef enum { _timer1, _timer2, _timer3, _timer4, _timer5, _Nbr_16timers } timer16_Sequence_t ;
#define Servo_VERSION 2 // software version of this library
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo (0.544ms)
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo (2,4ms)
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached (1.5ms)
#define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds (20ms)
#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
#define INVALID_SERVO 255 // flag indicating an invalid servo index
typedef struct {
uint8_t nbr :6 ; // a pin number from 0 to 63
uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
} ServoPin_t ;
typedef struct {
ServoPin_t Pin;
volatile unsigned int ticks;
} servo_t;
class Servo
{
public:
Servo();
uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
void detach();
void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
int read(); // returns current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
bool attached(); // return true if this servo is attached, otherwise false
private:
uint8_t servoIndex; // index into the channel data for this servo
int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
};
#endif

View File

@@ -1,22 +0,0 @@
// Controlling a servo position using a potentiometer (variable resistor)
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}

View File

@@ -1,31 +0,0 @@
// Sweep
// by BARRAGAN <http://barraganstudio.com>
// This example code is in the public domain.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created
int pos = 0; // variable to store the servo position
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=1; pos-=1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}

View File

@@ -1,24 +0,0 @@
#######################################
# Syntax Coloring Map Servo
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Servo KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
attach KEYWORD2
detach KEYWORD2
write KEYWORD2
read KEYWORD2
attached KEYWORD2
writeMicroseconds KEYWORD2
readMicroseconds KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -1,40 +0,0 @@
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <KeyboardController.h>
extern "C" {
void __keyboardControllerEmptyCallback() { }
}
void keyPressed() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback")));
void keyReleased() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback")));
void KeyboardController::OnKeyDown(uint8_t _mod, uint8_t _oemKey) {
modifiers = _mod;
keyOem = _oemKey;
key = OemToAscii(_mod, _oemKey);
keyPressed();
}
void KeyboardController::OnKeyUp(uint8_t _mod, uint8_t _oemKey) {
modifiers = _mod;
keyOem = _oemKey;
key = OemToAscii(_mod, _oemKey);
keyReleased();
}

View File

@@ -1,54 +0,0 @@
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef KEYBOARD_CONTROLLER_H
#define KEYBOARD_CONTROLLER_H
#include <hidboot.h>
enum KeyboardModifiers {
LeftCtrl = 1,
LeftShift = 2,
Alt = 4,
LeftCmd = 8,
RightCtrl = 16,
RightShift = 32,
AltGr = 64,
RightCmd = 128
};
class KeyboardController : public KeyboardReportParser {
public:
KeyboardController(USBHost &usb) : hostKeyboard(&usb), key(0), keyOem(0), modifiers(0) {
hostKeyboard.SetReportParser(0, this);
};
uint8_t getKey() { return key; };
uint8_t getModifiers() { return modifiers; };
uint8_t getOemKey() { return keyOem; };
protected:
virtual void OnKeyDown(uint8_t mod, uint8_t key);
virtual void OnKeyUp(uint8_t mod, uint8_t key);
private:
HIDBoot<HID_PROTOCOL_KEYBOARD> hostKeyboard;
uint8_t key, keyOem, modifiers;
};
#endif

View File

@@ -1,83 +0,0 @@
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MouseController.h>
extern "C" {
void __mouseControllerEmptyCallback() { }
}
void mouseClicked() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseDragged() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseMoved() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mousePressed() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseReleased() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
int MouseController::getXChange() {
int r = dx;
dx = 0;
return r;
}
int MouseController::getYChange() {
int r = dy;
dy = 0;
return r;
}
void MouseController::OnMouseMove(MOUSEINFO *mi) {
dx += mi->dX;
dy += mi->dY;
if (buttons != 0)
mouseDragged();
else
mouseMoved();
}
void MouseController::OnLeftButtonUp(MOUSEINFO *mi) {
buttons &= ~LEFT_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnLeftButtonDown(MOUSEINFO *mi) {
buttons |= LEFT_BUTTON;
mousePressed();
}
void MouseController::OnMiddleButtonUp(MOUSEINFO *mi) {
buttons &= ~MIDDLE_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnMiddleButtonDown(MOUSEINFO *mi) {
buttons |= MIDDLE_BUTTON;
mousePressed();
}
void MouseController::OnRightButtonUp(MOUSEINFO *mi) {
buttons &= ~RIGHT_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnRightButtonDown(MOUSEINFO *mi) {
buttons |= RIGHT_BUTTON;
mousePressed();
}

View File

@@ -1,57 +0,0 @@
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MOUSE_CONTROLLER_H
#define MOUSE_CONTROLLER_H
#include <hidboot.h>
enum MouseButton {
LEFT_BUTTON = 0x01,
MIDDLE_BUTTON = 0x02,
RIGHT_BUTTON = 0x04
};
class MouseController : public MouseReportParser
{
public:
MouseController(USBHost &usb) : hostMouse(&usb), dx(0), dy(0), buttons(0) {
hostMouse.SetReportParser(0, this);
};
bool getButton(MouseButton button) { return (buttons & button) == button; };
int getXChange();
int getYChange();
// int getWheelChange(); // Not implemented
protected:
virtual void OnMouseMove(MOUSEINFO *mi);
virtual void OnLeftButtonUp(MOUSEINFO *mi);
virtual void OnLeftButtonDown(MOUSEINFO *mi);
virtual void OnMiddleButtonUp(MOUSEINFO *mi);
virtual void OnMiddleButtonDown(MOUSEINFO *mi);
virtual void OnRightButtonUp(MOUSEINFO *mi);
virtual void OnRightButtonDown(MOUSEINFO *mi);
private:
HIDBoot<HID_PROTOCOL_MOUSE> hostMouse;
int dx, dy;
int buttons;
};
#endif

View File

@@ -1,7 +0,0 @@
This is the most reliable library to control the USB host chip MAX3421E. It is used to handle the communication between the Arduino ADK board and Android devices supporting Accessory mode. It of course works with other devices, but documenting that is outside our scope.
It is of course based in the original by CircuitsAtHome.com and has been patched by Follower (RancidBacon.com)
CircuitsAtHome has discontinued the development of this project. The Arduino Team commissioned a patch to the library to make it reliable up to a 99%.
CircuitsAtHome revision of the code can be found at https://github.com/felis/USB_Host_Shield_2.0. However the Arduino Team does not recommend using that library, yet, with ADK compatible boards, as v1 is much more stable.

View File

@@ -1,856 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
/* USB functions */
#include "Arduino.h"
#include "Usb.h"
#include <stdio.h>
static uint32_t usb_error = 0;
static uint32_t usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
/**
* \brief USBHost class constructor.
*/
USBHost::USBHost() : bmHubPre(0)
{
// Set up state machine
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
// Init host stack
init();
}
/**
* \brief Initialize USBHost class.
*/
void USBHost::init()
{
devConfigIndex = 0;
bmHubPre = 0;
}
/**
* \brief Get USBHost state.
*
* \return USB enumeration status (see USBHost::task).
*/
uint32_t USBHost::getUsbTaskState(void)
{
return (usb_task_state);
}
/**
* \brief Set USB state.
*
* \param state New USBHost status to be set.
*/
void USBHost::setUsbTaskState(uint32_t state)
{
usb_task_state = state;
}
/**
* \brief Get endpoint info from USB device address and device endpoint.
*
* \note This function should be used to know which host pipe is being used for
* the corresponding device endpoint.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
*
* \return Pointer to an EpInfo structure.
*/
EpInfo* USBHost::getEpInfoEntry(uint32_t addr, uint32_t ep)
{
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if (!p || !p->epinfo)
return NULL;
EpInfo *pep = p->epinfo;
for (uint32_t i = 0; i < p->epcount; i++)
{
if (pep->deviceEpNum == ep)
return pep;
pep++;
}
return NULL;
}
/**
* \brief Set device endpoint entry.
*
* \note Each device is different and has a different number of endpoints.
* This function sets endpoint record structure to the device using address
* addr in the address pool.
*
* \param ul_pipe Pipe address.
* \param ul_token_type Token type.
*
* \retval 0 on success.
* \retval USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL device not found.
*/
uint32_t USBHost::setEpInfoEntry(uint32_t addr, uint32_t epcount, EpInfo* eprecord_ptr)
{
if (!eprecord_ptr)
return USB_ERROR_INVALID_ARGUMENT;
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->address = addr;
p->epinfo = eprecord_ptr;
p->epcount = epcount;
return 0;
}
/**
* \brief Set host pipe target address and set ppep pointer to the endpoint
* structure matching the specified USB device address and endpoint.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param ppep Endpoint info structure pointer set by setPipeAddress.
* \param nak_limit Maximum number of NAK permitted.
*
* \retval 0 on success.
* \retval USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL device not found.
* \retval USB_ERROR_EPINFO_IS_NULL no endpoint structure found for this device.
* \retval USB_ERROR_EP_NOT_FOUND_IN_TBL the specified device endpoint cannot be found.
*/
uint32_t USBHost::setPipeAddress(uint32_t addr, uint32_t ep, EpInfo **ppep, uint32_t &nak_limit)
{
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo)
return USB_ERROR_EPINFO_IS_NULL;
*ppep = getEpInfoEntry(addr, ep);
if (!*ppep)
return USB_ERROR_EP_NOT_FOUND_IN_TBL;
nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
nak_limit--;
// Set peripheral address
TRACE_USBHOST(printf(" => SetAddress deviceEP=%lu configued as hostPIPE=%lu sending to address=%lu\r\n", ep, (*ppep)->hostPipeNum, addr);)
uhd_configure_address((*ppep)->hostPipeNum, addr);
return 0;
}
/**
* \brief Send a control request.
* Sets address, endpoint, fills control packet with necessary data, dispatches
* control packet, and initiates bulk IN transfer depending on request.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param bmReqType Request direction.
* \param bRequest Request type.
* \param wValLo Value low.
* \param wValHi Value high.
* \param wInd Index field.
* \param total Request length.
* \param nbytes Number of bytes to read.
* \param dataptr Data pointer.
* \param p USB class reader.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint16_t total, uint32_t nbytes, uint8_t* dataptr, USBReadParser *p)
{
// Request direction, IN or OUT
uint32_t direction = 0;
uint32_t rcode = 0;
SETUP_PKT setup_pkt;
EpInfo *pep = 0;
uint32_t nak_limit;
TRACE_USBHOST(printf(" => ctrlReq\r\n");)
// Set peripheral address
rcode = setPipeAddress(addr, ep, &pep, nak_limit);
if (rcode)
return rcode;
// Allocate Pipe0 with default 64 bytes size if not already initialized
// TODO : perform a get device descriptor first to get device endpoint size (else data can be missed if device ep0 > host pipe0)
rcode = UHD_Pipe0_Alloc(0, 64);
if (rcode)
{
TRACE_USBHOST(printf("/!\\ USBHost::ctrlReq : EP0 allocation error: %lu\r\n", rcode);)
return (rcode);
}
// Determine request direction
direction = ((bmReqType & 0x80 ) > 0);
// Fill in setup packet
setup_pkt.ReqType_u.bmRequestType = bmReqType;
setup_pkt.bRequest = bRequest;
setup_pkt.wVal_u.wValueLo = wValLo;
setup_pkt.wVal_u.wValueHi = wValHi;
setup_pkt.wIndex = wInd;
setup_pkt.wLength = total;
// Configure and write the setup packet into the FIFO
uhd_configure_pipe_token(0, tokSETUP);
UHD_Pipe_Write(pep->hostPipeNum, 8, (uint8_t *)&setup_pkt);
// Dispatch packet
rcode = dispatchPkt(tokSETUP, pep->hostPipeNum, nak_limit);
if (rcode)
{
// Return HRSLT if not zero
TRACE_USBHOST(printf("/!\\ USBHost::ctrlReq : Setup packet error: %lu\r\n", rcode);)
return (rcode);
}
// Data stage (if present)
if (dataptr != 0)
{
if (direction)
{
// IN transfer
TRACE_USBHOST(printf(" => ctrlData IN\r\n");)
uint32_t left = total;
while (left)
{
// Bytes read into buffer
uint32_t read = nbytes;
rcode = InTransfer(pep, nak_limit, &read, dataptr);
if (rcode)
return rcode;
// Invoke callback function if inTransfer completed successfuly and callback function pointer is specified
if (!rcode && p)
((USBReadParser*)p)->Parse(read, dataptr, total - left);
left -= read;
if (read < nbytes)
break;
}
}
else
{
// OUT transfer
TRACE_USBHOST(printf(" => ctrlData OUT\r\n");)
rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
}
if (rcode)
{
TRACE_USBHOST(printf("/!\\ USBHost::ctrlData : Data packet error: %lu\r\n", rcode);)
return (rcode);
}
}
// Status stage
return dispatchPkt((direction) ? tokOUTHS : tokINHS, pep->hostPipeNum, nak_limit);
}
/**
* \brief Perform IN request to the specified USB device.
*
* \note This function handles multiple packets (if necessary) and can
* receive a maximum of 'nbytesptr' bytes. It keep sending INs and writes data
* to memory area pointed by 'data'. The actual amount of received bytes is
* stored in 'nbytesptr'.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytesptr Receive buffer size. It is set to the amount of received
* bytes when the function returns.
* \param data Buffer to store received data.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::inTransfer(uint32_t addr, uint32_t ep, uint32_t *nbytesptr, uint8_t* data)
{
EpInfo *pep = NULL;
uint32_t nak_limit = 0;
uint32_t rcode = setPipeAddress(addr, ep, &pep, nak_limit);
if (rcode)
{
return rcode;
}
return InTransfer(pep, nak_limit, nbytesptr, data);
}
uint32_t USBHost::InTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t *nbytesptr, uint8_t* data)
{
uint32_t rcode = 0;
uint32_t pktsize = 0;
uint32_t nbytes = *nbytesptr;
uint32_t maxpktsize = pep->maxPktSize;
*nbytesptr = 0;
while (1)
{
// Use a 'return' to exit this loop
// IN packet to EP-'endpoint'. Function takes care of NAKS.
rcode = dispatchPkt(tokIN, pep->hostPipeNum, nak_limit);
if (rcode)
{
if (rcode == 1)
{
// Pipe freeze is mandatory to avoid sending IN endlessly (else reception becomes messy then)
uhd_freeze_pipe(pep->hostPipeNum);
}
// Should be 1, indicating NAK. Else return error code.
return rcode;
}
// Number of received bytes
pktsize = uhd_byte_count(pep->hostPipeNum);
if (nbytes < pktsize)
{
TRACE_USBHOST(printf("/!\\ USBHost::InTransfer : receive buffer is too small, size=%lu, expected=%lu\r\n", nbytes, pktsize);)
}
data += UHD_Pipe_Read(pep->hostPipeNum, pktsize, data);
// Add this packet's byte count to total transfer length
*nbytesptr += pktsize;
// The transfer is complete under two conditions:
// 1. The device sent a short packet (L.T. maxPacketSize)
// 2. 'nbytes' have been transferred.
if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes))
{
return 0;
}
}
}
/**
* \brief Perform OUT request to the specified USB device.
*
* \note This function handles multiple packets (if necessary) and sends
* 'nbytes' bytes.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytes Buffer size to be sent.
* \param data Buffer to send.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data)
{
EpInfo *pep = NULL;
uint32_t nak_limit = 0;
uint32_t rcode = setPipeAddress(addr, ep, &pep, nak_limit);
if (rcode)
{
return rcode;
}
return OutTransfer(pep, nak_limit, nbytes, data);
}
uint32_t USBHost::OutTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t nbytes, uint8_t *data)
{
uint32_t rcode = 0;
uint32_t bytes_tosend = 0;
uint32_t bytes_left = nbytes;
uint32_t maxpktsize = pep->maxPktSize;
if (maxpktsize < 1)
return USB_ERROR_INVALID_MAX_PKT_SIZE;
while (bytes_left)
{
bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
// Write FIFO
UHD_Pipe_Write(pep->hostPipeNum, bytes_tosend, data);
// Use a 'return' to exit this loop
// OUT packet to EP-'endpoint'. Function takes care of NAKS.
rcode = dispatchPkt(tokOUT, pep->hostPipeNum, nak_limit);
if (rcode)
{
// Should be 0, indicating ACK. Else return error code.
return rcode;
}
bytes_left -= bytes_tosend;
data += bytes_tosend;
}
// Should be 0 in all cases
return rcode;
}
/**
* \brief Dispatch USB packet.
*
* \note Ensure peripheral address is set and relevant buffer is loaded/empty.
* If NAK, tries to re-send up to nak_limit times.
* If nak_limit == 0, do not count NAKs, exit after timeout.
*
* \param token Token type (Setup, In or Out).
* \param hostPipeNum Host pipe number to use for sending USB packet.
* \param nak_limit Maximum number of NAK permitted.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t hostPipeNum, uint32_t nak_limit)
{
uint32_t timeout = millis() + USB_XFER_TIMEOUT;
uint32_t nak_count = 0;
uint32_t rcode = USB_ERROR_TRANSFER_TIMEOUT;
TRACE_USBHOST(printf(" => dispatchPkt token=%lu pipe=%lu nak_limit=%lu\r\n", token, hostPipeNum, nak_limit);)
// Launch the transfer
UHD_Pipe_Send(hostPipeNum, token);
// Check timeout but don't hold timeout if VBUS is lost
while ((timeout > millis()) && (UHD_GetVBUSState() == UHD_STATE_CONNECTED))
{
// Wait for transfer completion
if (UHD_Pipe_Is_Transfer_Complete(hostPipeNum, token))
{
return 0;
}
// Is NAK received?
if (Is_uhd_nak_received(hostPipeNum))
{
uhd_ack_nak_received(hostPipeNum);
nak_count++;
if (nak_limit && (nak_count == nak_limit))
{
// Return NAK
return 1;
}
}
}
return rcode;
}
/**
* \brief Configure device using known device classes.
* The device get a new address even if its class remain unknown.
*
* \param parent USB device address of the device's parent (0 if root).
* \param port USB device base address (see AddressPoolImpl).
* \param lowspeed Device speed.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::Configuring(uint32_t parent, uint32_t port, uint32_t lowspeed)
{
uint32_t rcode = 0;
for (; devConfigIndex < USB_NUMDEVICES; ++devConfigIndex)
{
if (!devConfig[devConfigIndex])
continue;
rcode = devConfig[devConfigIndex]->Init(parent, port, lowspeed);
if (!rcode)
{
TRACE_USBHOST(printf("USBHost::Configuring : found device class!\r\n");)
devConfigIndex = 0;
return 0;
}
if (rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
{
TRACE_USBHOST(printf("USBHost::Configuring : ERROR : device not supported!\r\n");)
}
else if (rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)
{
TRACE_USBHOST(printf("USBHost::Configuring : ERROR : class instance already in use!\r\n");)
}
else
{
// in case of an error devConfigIndex should be reset to 0
// in order to start from the very beginning the next time
// the program gets here
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
devConfigIndex = 0;
return rcode;
}
}
// Device class is not supported by any of the registered classes
devConfigIndex = 0;
rcode = DefaultAddressing(parent, port, lowspeed);
return rcode;
}
/**
* \brief Configure device with unknown USB class.
*
* \param parent USB device address of the device's parent (0 if root).
* \param port USB device base address (see AddressPoolImpl).
* \param lowspeed Device speed.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::DefaultAddressing(uint32_t parent, uint32_t port, uint32_t lowspeed)
{
uint32_t rcode = 0;
UsbDevice *p0 = 0, *p = 0;
// Get pointer to pseudo device with address 0 assigned
p0 = addrPool.GetUsbDevicePtr(0);
if (!p0)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p0->epinfo)
return USB_ERROR_EPINFO_IS_NULL;
p0->lowspeed = (lowspeed) ? 1 : 0;
// Allocate new address according to device class
uint32_t bAddress = addrPool.AllocAddress(parent, 0, port);
if (!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
p = addrPool.GetUsbDevicePtr(bAddress);
if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed;
// Assign new address to the device
rcode = setAddr(0, 0, bAddress);
if (rcode)
{
TRACE_USBHOST(printf("/!\\ USBHost::DefaultAddressing : Set address failed with code: %lu\r\n", rcode);)
addrPool.FreeAddress(bAddress);
bAddress = 0;
return rcode;
}
return 0;
}
/**
* \brief Release device and free associated resources.
*
* \param addr USB device address.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::ReleaseDevice(uint32_t addr)
{
if (!addr)
return 0;
for (uint32_t i = 0; i < USB_NUMDEVICES; ++i)
{
if (devConfig[i]->GetAddress() == addr)
{
return devConfig[i]->Release();
}
}
return 0;
}
/**
* \brief Get device descriptor.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytes Buffer size.
* \param dataptr Buffer to store received descriptor.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr)
{
return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, 0));
}
/**
* \brief Get configuration descriptor.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytes Buffer size.
* \param conf Configuration number.
* \param dataptr Buffer to store received descriptor.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint32_t conf, uint8_t* dataptr)
{
return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, 0));
}
/**
* \brief Get configuration descriptor and extract endpoints using USBReadParser object.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param conf Configuration number.
* \param p USBReadParser object pointer used to extract endpoints.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t conf, USBReadParser *p)
{
const uint32_t bufSize = 64;
uint8_t buf[bufSize];
uint32_t ret = getConfDescr(addr, ep, 8, conf, buf);
if (ret)
return ret;
uint32_t total = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength;
delay(100);
return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
}
/**
* \brief Get string descriptor.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytes Buffer size.
* \param index String index.
* \param langid Language ID.
* \param dataptr Buffer to store received descriptor.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr)
{
return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, nbytes, dataptr, 0));
}
/**
* \brief Set USB device address.
*
* \param oldaddr Current USB device address.
* \param ep USB device endpoint number.
* \param addr New USB device address to be set.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr)
{
TRACE_USBHOST(printf(" => USBHost::setAddr\r\n");)
return ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, 0, 0);
}
/**
* \brief Set configuration.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param conf_value New configuration value to be set.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::setConf(uint32_t addr, uint32_t ep, uint32_t conf_value)
{
return (ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, 0, 0));
}
/**
* \brief USB main task, responsible for enumeration and clean up stage.
*
* \note Must be periodically called from loop().
*/
void USBHost::Task(void)
{
uint32_t rcode = 0;
volatile uint32_t tmpdata = 0;
static uint32_t delay = 0;
uint32_t lowspeed = 0;
// Update USB task state on Vbus change
tmpdata = UHD_GetVBUSState();
switch (tmpdata)
{
case UHD_STATE_ERROR:
// Illegal state
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
lowspeed = 0;
break;
case UHD_STATE_DISCONNECTED:
// Disconnected state
if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
{
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
lowspeed = 0;
}
break;
case UHD_STATE_CONNECTED:
// Attached state
if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED)
{
delay = millis() + USB_SETTLE_DELAY;
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
//FIXME TODO: lowspeed = 0 ou 1; already done by hardware?
}
break;
}
// Poll connected devices (if required)
for (uint32_t i = 0; i < USB_NUMDEVICES; ++i)
if (devConfig[i])
rcode = devConfig[i]->Poll();
// Perform USB enumeration stage and clean up
switch (usb_task_state)
{
case USB_DETACHED_SUBSTATE_INITIALIZE:
TRACE_USBHOST(printf(" + USB_DETACHED_SUBSTATE_INITIALIZE\r\n");)
// Init USB stack and driver
UHD_Init();
init();
// Free all USB resources
for (uint32_t i = 0; i < USB_NUMDEVICES; ++i)
if (devConfig[i])
rcode = devConfig[i]->Release();
usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
break;
case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE:
// Nothing to do
break;
case USB_DETACHED_SUBSTATE_ILLEGAL:
// Nothing to do
break;
case USB_ATTACHED_SUBSTATE_SETTLE:
// Settle time for just attached device
if (delay < millis())
{
TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_SETTLE\r\n");)
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
}
break;
case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_RESET_DEVICE\r\n");)
// Trigger Bus Reset
UHD_BusReset();
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
break;
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
if (Is_uhd_reset_sent())
{
TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE\r\n");)
// Clear Bus Reset flag
uhd_ack_reset_sent();
// Enable Start Of Frame generation
uhd_enable_sof();
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
// Wait 20ms after Bus Reset (USB spec)
delay = millis() + 20;
}
break;
case USB_ATTACHED_SUBSTATE_WAIT_SOF:
// Wait for SOF received first
if (Is_uhd_sof())
{
if (delay < millis())
{
TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_SOF\r\n");)
// 20ms waiting elapsed
usb_task_state = USB_STATE_CONFIGURING;
}
}
break;
case USB_STATE_CONFIGURING:
TRACE_USBHOST(printf(" + USB_STATE_CONFIGURING\r\n");)
rcode = Configuring(0, 0, lowspeed);
if (rcode)
{
TRACE_USBHOST(printf("/!\\ USBHost::Task : USB_STATE_CONFIGURING failed with code: %lu\r\n", rcode);)
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
{
usb_error = rcode;
usb_task_state = USB_STATE_ERROR;
}
}
else
{
usb_task_state = USB_STATE_RUNNING;
TRACE_USBHOST(printf(" + USB_STATE_RUNNING\r\n");)
}
break;
case USB_STATE_RUNNING:
break;
case USB_STATE_ERROR:
break;
}
}

View File

@@ -1,230 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
/* USB functions */
#ifndef USB_H_INCLUDED
#define USB_H_INCLUDED
//#define TRACE_USBHOST(x) x
#define TRACE_USBHOST(x)
#include <stdint.h>
#include "usb_ch9.h"
#include "address.h"
/* Common setup data constant combinations */
#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE // Get descriptor request type
#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE // Set request type for all but 'set feature' and 'set interface'
#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE // Get interface request type
// USB Device Classes
#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors
#define USB_CLASS_AUDIO 0x01 // Audio
#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control
#define USB_CLASS_HID 0x03 // HID
#define USB_CLASS_PHYSICAL 0x05 // Physical
#define USB_CLASS_IMAGE 0x06 // Image
#define USB_CLASS_PRINTER 0x07 // Printer
#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage
#define USB_CLASS_HUB 0x09 // Hub
#define USB_CLASS_CDC_DATA 0x0a // CDC-Data
#define USB_CLASS_SMART_CARD 0x0b // Smart-Card
#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security
#define USB_CLASS_VIDEO 0x0e // Video
#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare
#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device
#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller
#define USB_CLASS_MISC 0xef // Miscellaneous
#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific
#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific
// Additional Error Codes
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1
#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2
#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4
#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6
#define USB_ERROR_EPINFO_IS_NULL 0xD7
#define USB_ERROR_INVALID_ARGUMENT 0xD8
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9
#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA
#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB
#define USB_ERROR_TRANSFER_TIMEOUT 0xFF
#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
//#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. 0 means NAKs are not counted
#define USB_RETRY_LIMIT 3 //retry limit for a transfer
#define USB_SETTLE_DELAY 200 //settle delay in milliseconds
#define USB_NUMDEVICES 16 //number of USB devices
//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller
#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms
/* USB state machine states */
#define USB_STATE_MASK 0xf0
#define USB_STATE_DETACHED 0x10
#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11
#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12
#define USB_DETACHED_SUBSTATE_ILLEGAL 0x13
#define USB_ATTACHED_SUBSTATE_SETTLE 0x20
#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30
#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40
#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50
#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60
#define USB_STATE_ADDRESSING 0x70
#define USB_STATE_CONFIGURING 0x80
#define USB_STATE_RUNNING 0x90
#define USB_STATE_ERROR 0xa0
#define USB_STATE_MASK 0xf0
// USB Setup Packet Structure
typedef struct
{
union
{ // offset description
uint8_t bmRequestType; // 0 Bit-map of request type
struct
{
uint8_t recipient: 5; // Recipient of the request
uint8_t type: 2; // Type of request
uint8_t direction: 1; // Direction of data X-fer
};
} ReqType_u;
uint8_t bRequest; // 1 Request
union
{
uint16_t wValue; // 2 Depends on bRequest
struct
{
uint8_t wValueLo;
uint8_t wValueHi;
};
} wVal_u;
uint16_t wIndex; // 4 Depends on bRequest
uint16_t wLength; // 6 Depends on bRequest
} SETUP_PKT, *PSETUP_PKT;
/**
* \class USBReadParser
*
* \brief Base class used for USB descriptor parsing.
*/
class USBReadParser
{
public:
virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset) = 0;
};
/**
* \class USBDeviceConfig
*
* \brief Device configuration class used for managing device life cycle.
*/
class USBDeviceConfig
{
public:
//! @brief Perform final enumeration stage.
virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed) = 0;
//! @brief Free USB allocated resources (pipes and address).
virtual uint32_t Release() = 0;
//! @brief Poll USB device. Call is made for each connected USB device on USBHost.task() call.
virtual uint32_t Poll() = 0;
//! @brief Retrieve USB device address.
virtual uint32_t GetAddress() = 0;
};
/**
* \class USBHost
*
* \brief Main USB host class.
*/
class USBHost
{
AddressPoolImpl<USB_NUMDEVICES> addrPool;
USBDeviceConfig* devConfig[USB_NUMDEVICES];
uint32_t devConfigIndex;
uint32_t bmHubPre;
public:
USBHost(void);
//void SetHubPreMask() { bmHubPre |= bmHUBPRE; };
//void ResetHubPreMask() { bmHubPre &= (~bmHUBPRE); };
AddressPool& GetAddressPool()
{
return (AddressPool&)addrPool;
};
uint32_t RegisterDeviceClass(USBDeviceConfig *pdev)
{
for (uint32_t i = 0; i < USB_NUMDEVICES; ++i)
{
if (!devConfig[i])
{
devConfig[i] = pdev;
return 0;
}
}
return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
};
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
{
addrPool.ForEachUsbDevice(pfunc);
};
uint32_t getUsbTaskState(void);
void setUsbTaskState(uint32_t state);
EpInfo* getEpInfoEntry(uint32_t addr, uint32_t ep);
uint32_t setEpInfoEntry(uint32_t addr, uint32_t epcount, EpInfo* eprecord_ptr);
/* Control requests */
uint32_t getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr);
uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint32_t conf, uint8_t* dataptr);
uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t conf, USBReadParser *p);
uint32_t getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr);
uint32_t setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr);
uint32_t setConf(uint32_t addr, uint32_t ep, uint32_t conf_value);
uint32_t ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
uint16_t wInd, uint16_t total, uint32_t nbytes, uint8_t* dataptr, USBReadParser *p);
/* Transfer requests */
uint32_t inTransfer(uint32_t addr, uint32_t ep, uint32_t *nbytesptr, uint8_t* data);
uint32_t outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data);
uint32_t dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit);
void Task(void);
uint32_t DefaultAddressing(uint32_t parent, uint32_t port, uint32_t lowspeed);
uint32_t Configuring(uint32_t parent, uint32_t port, uint32_t lowspeed);
uint32_t ReleaseDevice(uint32_t addr);
private:
void init();
uint32_t setPipeAddress(uint32_t addr, uint32_t ep, EpInfo **ppep, uint32_t &nak_limit);
uint32_t OutTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t nbytes, uint8_t *data);
uint32_t InTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t *nbytesptr, uint8_t* data);
};
#endif /* USB_H_INCLUDED */

View File

@@ -1,392 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#ifndef ADDRESS_H_INCLUDED
#define ADDRESS_H_INCLUDED
#include <stdint.h>
/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
#define USB_NAK_MAX_POWER 16 //NAK binary order maximum value
#define USB_NAK_DEFAULT 14 //default 16K-1 NAKs before giving up
#define USB_NAK_NOWAIT 1 //Single NAK stops transfer
#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
/**
* \brief Device endpoint definition.
*
* \note hostPipeNum is the allocated pipe used for the communication with
* deviceEpNum remote device endpoint.
* There is exactly one hostPipeNum corresponding to a deviceEpNum.
*
* \note The number of host pipe is limited by the hardware (10 on SAM3X).
* Moreover hostPipeNum allocation is static, meaning that only a limited
* amount of device endpoints can be opened at the same time, thus limitating
* the maximum number of connected devices at the same time.
*/
struct EpInfo
{
uint32_t deviceEpNum; // Device endpoint number
uint32_t hostPipeNum; // Host corresponding pipe number
uint32_t maxPktSize; // Maximum packet size
union
{
uint8_t epAttribs;
struct
{
uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
};
};
};
/**
* \brief USB device address definition.
*
* \note The 8 bits USB address is defined like this:
*
* 7 6 5 4 3 2 1 0
* ---------------------------------
* | | H | P | P | P | A | A | A |
* ---------------------------------
*
* H - if 1 the address is a hub address
* P - parent hub address
* A - device address / port number in case of hub
*/
struct UsbDeviceAddress
{
union
{
struct
{
uint32_t bmAddress : 3; // device address/port number
uint32_t bmParent : 3; // parent hub address
uint32_t bmHub : 1; // hub flag
uint32_t bmReserved : 25; // reserved, must be zerro
};
uint32_t devAddress;
};
};
#define bmUSB_DEV_ADDR_ADDRESS 0x07
#define bmUSB_DEV_ADDR_PARENT 0x38
#define bmUSB_DEV_ADDR_HUB 0x40
/**
* \brief USB device definition.
*
* \note epinfo is used to store the list of device endpoints currently used
* by the USBHost stack. This field is set during enumeration process when
* a supported USB class is found. See any USB classes implementing
* USBDeviceConfig and init() method for reference.
*/
struct UsbDevice
{
EpInfo *epinfo; // endpoint info pointer
uint32_t address; // address
uint32_t epcount; // number of endpoints
uint32_t lowspeed; // indicates if a device is the low speed one
};
/**
* \class Abstract AddressPool definition.
*/
class AddressPool
{
public:
virtual UsbDevice* GetUsbDevicePtr(uint32_t addr) = 0;
virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0) = 0;
virtual void FreeAddress(uint32_t addr) = 0;
};
typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
#define ADDR_ERROR_INVALID_INDEX 0xFF
#define ADDR_ERROR_INVALID_ADDRESS 0xFF
/**
* \class AddressPoolImpl definition.
* Used to store the list of connected devices and to keep track of free USB
* addresses.
*/
template <const uint32_t MAX_DEVICES_ALLOWED>
class AddressPoolImpl : public AddressPool
{
private:
EpInfo dev0ep; // Endpoint data structure used during enumeration for uninitialized device
uint32_t hubCounter; // hub counter is kept
// in order to avoid hub address duplication
UsbDevice thePool[MAX_DEVICES_ALLOWED];
/**
* \brief Initialize the specified address pool entry.
*
* \param index Index pointing to a UsbDevice instance in the address pool.
*/
void InitEntry(uint32_t index)
{
thePool[index].address = 0;
thePool[index].epcount = 1;
thePool[index].lowspeed = 0;
thePool[index].epinfo = &dev0ep;
};
/**
* \brief Return an address pool index for a given address. This index can
* further be used to retrieve the corresponding USB device instance
* UsbDevice.
*
* \param index Index pointing to a UsbDevice instance in the address pool.
*
* \return Index number if found, 0 otherwise.
* \note Index 0 is reserved for address 0 and shall never be used.
*/
uint32_t FindAddressIndex(uint32_t address = 0)
{
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
{
if (thePool[i].address == address)
return i;
}
return 0;
};
/**
* \brief Return address pool child index for a given parent. This index can
* further be used to retrieve the corresponding USB device instance
* UsbDevice.
*
* \param addr Parent USB address.
* \param start Search in the pool from this index. Calling multiple time
* this function with the returned index + 1 can be used to walk through
* all children.
*
* \return Child index number if found, 0 otherwise.
* \note Index 0 is reserved for address 0 and shall never be used.
*/
uint32_t FindChildIndex(UsbDeviceAddress addr, uint32_t start = 1)
{
for (uint32_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; ++i)
{
if (((UsbDeviceAddress*)&thePool[i].address)->bmParent == addr.bmAddress)
return i;
}
return 0;
};
/**
* \brief Free address entry specified by index parameter.
*
* \note Calling FreeAddressByIndex only frees the USB address for possible
* further assignement. However, it does not free the actual USB resources
* used by the device. This can be made by calling the release() method
* from any UsbDevice class implementing USBDeviceConfig.
*
* \param index Index pointing to a UsbDevice instance in the address pool.
*
* \note Calling FreeAddressByIndex with a 0 index param has no effect.
*/
void FreeAddressByIndex(uint32_t index)
{
// Zero field is reserved and should not be affected
if (index == 0)
return;
// If a hub was switched off all port addresses should be freed
if (((UsbDeviceAddress*)&thePool[index].address)->bmHub == 1)
{
for (uint32_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*)&thePool[index].address), i) > 0); )
FreeAddressByIndex(i);
// If the hub had the last allocated address, hubCounter should be decremented
if (hubCounter == ((UsbDeviceAddress*)&thePool[index].address)->bmAddress)
hubCounter --;
}
InitEntry(index);
}
/**
* \brief Initialize all address poll entries at once.
*/
void InitAllAddresses()
{
for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
InitEntry(i);
hubCounter = 0;
};
public:
/**
* \brief AddressPoolImpl class constructor.
*/
AddressPoolImpl() : hubCounter(0)
{
// Init address zero (reserved)
InitEntry(0);
// Init all remaing addresses
InitAllAddresses();
// Configure ep0 used for enumeration
dev0ep.deviceEpNum = 0;
dev0ep.hostPipeNum = 0;
dev0ep.maxPktSize = 8;
};
/**
* \brief Get a UsbDevice pointer from a USB device address.
*
* \param addr USB device address.
*
* \return UsbDevice pointer on success, 0 otherwise.
*/
virtual UsbDevice* GetUsbDevicePtr(uint32_t addr)
{
if (!addr)
return thePool;
uint32_t index = FindAddressIndex(addr);
return (!index) ? 0 : (thePool + index);
};
/**
* \brief Perform an operation specified by pfunc for each addressed
* USB device.
*
* \param pfunc Any function pointer with type UsbDeviceHandleFunc.
*/
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
{
if (!pfunc)
return;
for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if (thePool[i].address)
pfunc(thePool + i);
};
/**
* \brief Allocate a new USB device address.
*
* \note See UsbDeviceAddress definition for better understanding.
*
* \param parent USB device address of the Parent device.
* \param is_hub Set to true if the corresponding device is a Hub, false
* otherwise.
* \param port USB device base address.
*
* \return UsbDevice pointer on success, 0 otherwise.
*/
virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0)
{
if (parent > 127 || port > 7)
return 0;
if (is_hub && hubCounter == 7)
return 0;
// Finds first empty address entry starting from one
uint32_t index = FindAddressIndex(0);
// If empty entry is not found
if (!index)
return 0;
if (parent == 0)
{
if (is_hub)
{
thePool[index].address = 0x41;
hubCounter++;
}
else
thePool[index].address = 1;
return thePool[index].address;
}
UsbDeviceAddress addr;
addr.bmParent = ((UsbDeviceAddress*)&parent)->bmAddress;
if (is_hub)
{
addr.bmHub = 1;
addr.bmAddress = hubCounter++;
}
else
{
addr.bmHub = 0;
addr.bmAddress = port;
}
thePool[index].address = *((uint8_t*)&addr);
return thePool[index].address;
};
/**
* \brief Free the specified USB device address.
*
* \param addr USB device address to free.
*/
virtual void FreeAddress(uint32_t addr)
{
// If the root hub is disconnected all the addresses should be initialized
if (addr == 0x41)
{
InitAllAddresses();
return;
}
uint32_t index = FindAddressIndex(addr);
FreeAddressByIndex(index);
};
// Returns number of hubs attached
// It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
/*uint32_t GetNumHubs()
{
return hubCounter;
};
uint32_t GetNumDevices()
{
uint32_t counter = 0;
for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; ++i)
if (thePool[i].address != 0);
counter++;
return counter;
};*/
};
#endif /* ADDRESS_H_INCLUDED */

View File

@@ -1,405 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
/* Google ADK interface */
#include "adk.h"
const uint32_t ADK::epDataInIndex = 1;
const uint32_t ADK::epDataOutIndex = 2;
/**
* \brief ADK class constructor.
*/
ADK::ADK(USBHost *p, const char* pmanufacturer,
const char* pmodel,
const char* pdescription,
const char* pversion,
const char* puri,
const char* pserial) :
manufacturer(pmanufacturer),
model(pmodel),
description(pdescription),
version(pversion),
uri(puri),
serial(pserial),
pUsb(p),
bAddress(0),
bNumEP(1),
ready(false)
{
// Initialize endpoint data structures
for (uint32_t i = 0; i < ADK_MAX_ENDPOINTS; ++i)
{
epInfo[i].deviceEpNum = 0;
epInfo[i].hostPipeNum = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
// Register in USB subsystem
if (pUsb)
{
pUsb->RegisterDeviceClass(this);
}
}
/**
* \brief Initialize connection to an Android Phone.
*
* \param parent USB device address of the Parent device.
* \param port USB device base address.
* \param lowspeed USB device speed.
*
* \return 0 on success, error code otherwise.
*/
uint32_t ADK::Init(uint32_t parent, uint32_t port, uint32_t lowspeed)
{
uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)];
uint32_t rcode = 0;
UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL;
uint32_t adkproto = -1;
uint32_t num_of_conf = 0;
// Get memory address of USB device address pool
AddressPool &addrPool = pUsb->GetAddressPool();
TRACE_USBHOST(printf("ADK::Init\r\n");)
// Check if address has already been assigned to an instance
if (bAddress)
{
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
}
// Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0);
if (!p)
{
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
}
if (!p->epinfo)
{
return USB_ERROR_EPINFO_IS_NULL;
}
// Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo;
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo;
p->lowspeed = lowspeed;
// Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
// Restore p->epinfo
p->epinfo = oldep_ptr;
if (rcode)
{
goto FailGetDevDescr;
}
// Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port);
// Extract Max Packet Size from device descriptor
epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode)
{
p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
TRACE_USBHOST(printf("ADK::Init : setAddr failed with rcode %lu\r\n", rcode);)
return rcode;
}
TRACE_USBHOST(printf("ADK::Init : device address is now %lu\r\n", bAddress);)
p->lowspeed = false;
//get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress);
if (!p)
{
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
}
p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode)
{
goto FailSetDevTblEntry;
}
// Check if ADK device is already in accessory mode; if yes, configure and exit
if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor == ADK_VID &&
(((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADB_PID))
{
TRACE_USBHOST(printf("ADK::Init : Accessory mode device detected\r\n");)
/* Go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
TRACE_USBHOST(printf("ADK::Init : number of configuration is %lu\r\n", num_of_conf);)
for (uint32_t i = 0; i < num_of_conf; ++i)
{
ConfigDescParser<0, 0, 0, 0> confDescrParser(this);
delay(1);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
#if defined(XOOM)
//Added by Jaylen Scott Vanorden
if (rcode)
{
TRACE_USBHOST(printf("ADK::Init : Got 1st bad code for config: %lu\r\n", rcode);)
// Try once more
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
}
#endif
if (rcode)
{
goto FailGetConfDescr;
}
if (bNumEP > 2)
{
break;
}
}
if (bNumEP == 3)
{
// Assign epInfo to epinfo pointer - this time all 3 endpoins
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if (rcode)
{
goto FailSetDevTblEntry;
}
}
// Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode)
{
goto FailSetConf;
}
TRACE_USBHOST(printf("ADK::Init : ADK device configured successfully\r\n");)
ready = true;
return 0;
}
// Probe device - get accessory protocol revision
delay(1);
rcode = getProto((uint8_t*)&adkproto);
#if defined(XOOM)
// Added by Jaylen Scott Vanorden
if (rcode)
{
TRACE_USBHOST(printf("ADK::Init : Got 1st bad code for config: %lu\r\n", rcode);)
// Try once more
rcode = getProto((uint8_t*)&adkproto );
}
#endif
if (rcode)
{
goto FailGetProto;
}
TRACE_USBHOST(printf("ADK::Init : DK protocol rev. %lu", adkproto);)
// Send ID strings
sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer);
sendStr(ACCESSORY_STRING_MODEL, model);
sendStr(ACCESSORY_STRING_DESCRIPTION, description);
sendStr(ACCESSORY_STRING_VERSION, version);
sendStr(ACCESSORY_STRING_URI, uri);
sendStr(ACCESSORY_STRING_SERIAL, serial);
// Switch to accessory mode
// The Android phone will reset
rcode = switchAcc();
if (rcode)
{
goto FailSwAcc;
}
rcode = -1;
goto SwAttempt; // Switch to accessory mode
// Diagnostic messages
FailGetDevDescr:
TRACE_USBHOST(printf("ADK::Init getDevDescr : ");)
goto Fail;
FailSetDevTblEntry:
TRACE_USBHOST(printf("ADK::Init setDevTblEn : ");)
goto Fail;
FailGetProto:
TRACE_USBHOST(printf("ADK::Init getProto : ");)
goto Fail;
FailSwAcc:
TRACE_USBHOST(printf("ADK::Init swAcc : ");)
goto Fail;
SwAttempt:
TRACE_USBHOST(printf("ADK::Init Accessory mode switch attempt : ");)
goto Fail;
FailGetConfDescr:
TRACE_USBHOST(printf("ADK::Init getConf : ");)
goto Fail;
FailSetConf:
TRACE_USBHOST(printf("ADK::Init setConf : ");)
goto Fail;
Fail:
TRACE_USBHOST(printf("error code: %lu\r\n", rcode);)
Release();
return rcode;
}
/**
* \brief Extract bulk-IN and bulk-OUT endpoint information from configuration
* descriptor.
*
* \param conf Configuration number.
* \param iface Interface number.
* \param alt Alternate setting.
* \param proto Protocol version used.
* \param pep Pointer to endpoint descriptor.
*/
void ADK::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
{
if (bNumEP == 3)
{
return;
}
bConfNum = conf;
uint32_t index = 0;
uint32_t pipe = 0;
if ((pep->bmAttributes & 0x02) == 2)
{
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
}
// Fill in the endpoint info structure
epInfo[index].deviceEpNum = pep->bEndpointAddress & 0x0F;
epInfo[index].maxPktSize = pep->wMaxPacketSize;
TRACE_USBHOST(printf("ADK::EndpointXtract : Found new endpoint\r\n");)
TRACE_USBHOST(printf("ADK::EndpointXtract : deviceEpNum: %lu\r\n", epInfo[index].deviceEpNum);)
TRACE_USBHOST(printf("ADK::EndpointXtract : maxPktSize: %lu\r\n", epInfo[index].maxPktSize);)
TRACE_USBHOST(printf("ADK::EndpointXtract : index: %lu\r\n", index);)
if (index == epDataInIndex)
pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
else if (index == epDataOutIndex)
pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_OUT, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
// Ensure pipe allocation is okay
if (pipe == 0)
{
TRACE_USBHOST(printf("ADK::EndpointXtract : Pipe allocation failure\r\n");)
// Enumeration failed, so user should not perform write/read since isConnected will return false
return;
}
epInfo[index].hostPipeNum = pipe;
bNumEP++;
}
/**
* \brief Release USB allocated resources (pipes and address).
*
* \note Release call is made from USBHost.task() on disconnection events.
* \note Release call is made from Init() on enumeration failure.
*
* \return Always 0.
*/
uint32_t ADK::Release()
{
// Free allocated host pipes
UHD_Pipe_Free(epInfo[epDataInIndex].hostPipeNum);
UHD_Pipe_Free(epInfo[epDataOutIndex].hostPipeNum);
// Free allocated USB address
pUsb->GetAddressPool().FreeAddress(bAddress);
// Must have to be reset to 1
bNumEP = 1;
bAddress = 0;
ready = false;
return 0;
}
/**
* \brief Read from ADK.
*
* \param nreadbytes Return value containing the number of read bytes.
* \param datalen Buffer length.
* \param dataptr Buffer to store the incoming data.
*
* \return 0 on success, error code otherwise.
*/
uint32_t ADK::read(uint32_t *nreadbytes, uint32_t datalen, uint8_t *dataptr)
{
*nreadbytes = datalen;
return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].deviceEpNum, nreadbytes, dataptr);
}
/**
* \brief Write to ADK.
*
* \param datalen Amount of data to send. This parameter shall not exceed
* dataptr length.
* \param dataptr Buffer containing the data to be sent.
*
* \return 0 on success, error code otherwise.
*/
uint32_t ADK::write(uint32_t datalen, uint8_t *dataptr)
{
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].deviceEpNum, datalen, dataptr);
}

View File

@@ -1,150 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
/* Google ADK interface support header */
#ifndef ADK_H_INCLUDED
#define ADK_H_INCLUDED
#include <stdint.h>
#include "usb_ch9.h"
#include "Usb.h"
#include "hid.h"
#include "Arduino.h"
#include "confdescparser.h"
#define ADK_VID 0x18D1
#define ADK_PID 0x2D00
#define ADB_PID 0x2D01
#define XOOM //enables repeating getProto() and getConf() attempts
//necessary for slow devices such as Motorola XOOM
//defined by default, can be commented out to save memory
/* Requests */
#define ADK_GETPROTO 51 //check USB accessory protocol version
#define ADK_SENDSTR 52 //send identifying string
#define ADK_ACCSTART 53 //start device in accessory mode
#define bmREQ_ADK_GET USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
#define bmREQ_ADK_SEND USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
#define ACCESSORY_STRING_MANUFACTURER 0
#define ACCESSORY_STRING_MODEL 1
#define ACCESSORY_STRING_DESCRIPTION 2
#define ACCESSORY_STRING_VERSION 3
#define ACCESSORY_STRING_URI 4
#define ACCESSORY_STRING_SERIAL 5
#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT
/**
* \class ADK definition.
*/
class ADK : public USBDeviceConfig, public UsbConfigXtracter
{
private:
/* ID strings */
const char* manufacturer;
const char* model;
const char* description;
const char* version;
const char* uri;
const char* serial;
/* ADK proprietary requests */
uint32_t getProto(uint8_t* adkproto);
uint32_t sendStr(uint32_t index, const char* str);
uint32_t switchAcc(void);
protected:
static const uint32_t epDataInIndex; // DataIn endpoint index
static const uint32_t epDataOutIndex; // DataOUT endpoint index
/* Mandatory members */
USBHost *pUsb;
uint32_t bAddress; // Device USB address
uint32_t bConfNum; // configuration number
uint32_t bNumEP; // total number of EP in the configuration
bool ready;
/* Endpoint data structure describing the device EP */
EpInfo epInfo[ADK_MAX_ENDPOINTS];
public:
ADK(USBHost *pUsb, const char* pmanufacturer,
const char* pmodel,
const char* pdescription,
const char* pversion,
const char* puri,
const char* pserial);
// Methods for receiving and sending data
uint32_t read(uint32_t *nreadbytes, uint32_t datalen, uint8_t *dataptr);
uint32_t write(uint32_t datalen, uint8_t *dataptr);
// USBDeviceConfig implementation
virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
virtual uint32_t Release();
virtual uint32_t Poll() { return 0; }; // not implemented
virtual uint32_t GetAddress() { return bAddress; };
virtual bool isReady() { return ready; };
// UsbConfigXtracter implementation
virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
};
/**
* \brief Get ADK protocol version.
*
* \param adkproto Empty buffer to be filled by getProto (2 bytes) with the ADK
* protocol version value.
*
* \return 0 on success, error code otherwise.
*/
inline uint32_t ADK::getProto(uint8_t* adkproto)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
}
/**
* \brief Send ADK string.
*
* \param index String index.
* \param str String to send.
*
* \return 0 on success, error code otherwise.
*/
inline uint32_t ADK::sendStr(uint32_t index, const char* str)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL));
}
/**
* \brief Send a switch to accessory mode request.
*
* \return 0 on success, error code otherwise.
*/
inline uint32_t ADK::switchAcc(void)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
}
#endif /* ADK_H_INCLUDED */

View File

@@ -1,241 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#ifndef CONFDESCPARSER_H_INCLUDED
#define CONFDESCPARSER_H_INCLUDED
#include <stdint.h>
#include "parsetools.h"
/**
* \class Abstract UsbConfigXtracter definition.
*
* \note This class is used for extracting USB endpoint descriptors.
*/
class UsbConfigXtracter
{
public:
virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0;
};
#define CP_MASK_COMPARE_CLASS 1
#define CP_MASK_COMPARE_SUBCLASS 2
#define CP_MASK_COMPARE_PROTOCOL 4
#define CP_MASK_COMPARE_ALL 7
/**
* \class ConfigDescParser definition.
*
* \note This class is used for parsing configuration descriptors.
*/
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
class ConfigDescParser : public USBReadParser
{
UsbConfigXtracter *theXtractor;
MultiValueBuffer theBuffer;
MultiByteValueParser valParser;
ByteSkipper theSkipper;
uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
uint32_t stateParseDescr; // ParseDescriptor state
uint32_t dscrLen; // Descriptor length
uint32_t dscrType; // Descriptor type
bool isGoodInterface; // Apropriate interface flag
uint32_t confValue; // Configuration value
uint32_t protoValue; // Protocol value
uint32_t ifaceNumber; // Interface number
uint32_t ifaceAltSet; // Interface alternate settings
bool ParseDescriptor(uint8_t **pp, uint32_t *pcntdn);
void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
public:
ConfigDescParser(UsbConfigXtracter *xtractor);
virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset);
};
/**
* \brief ConfigDescParser class constructor.
*
* \param xtractor Is saved as ConfigDescParser attribute and later used as a
* callback for parsing the endpoint descriptors.
*
* \note During enumeration stage, all supported USB classes invoke
* ConfigDescParser with "this" as parameter, meaning that one class is also
* responsible for parsing its endpoint descriptors. This makes sense since
* each USB class handles different number of endpoints and configurations.
* For instance see ADK::Init from ADK class.
*/
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
theXtractor(xtractor),
stateParseDescr(0),
dscrLen(0),
dscrType(0)
{
theBuffer.pValue = varBuffer;
valParser.Initialize(&theBuffer);
theSkipper.Initialize(&theBuffer);
};
/**
* \brief Parse a complete USB configuration descriptor.
*
* \param len Buffer length.
* \param pbuf Buffer containing the configuration descriptor.
* \param offset Current offset position.
*/
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset)
{
uint32_t cntdn = len;
uint8_t *p = (uint8_t*)pbuf;
while (cntdn)
if (!ParseDescriptor(&p, &cntdn))
return;
}
/**
* \brief Parse a USB configuration descriptor.
* Takes values for class, subclass, protocol fields in interface descriptor
* and compare masks for them. When the match is found, calls EndpointXtract
* passing buffer containing endpoint descriptor.
*
* \note This method should not be called directly, use Parse() instead.
*
* \param pcntdn Buffer length.
* \param pp Buffer containing the configuration descriptor.
*
* \return true if data remains in the buffer for parsing, false otherwise.
*/
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint32_t *pcntdn)
{
switch (stateParseDescr)
{
case 0:
theBuffer.valueSize = 2;
valParser.Initialize(&theBuffer);
stateParseDescr = 1;
case 1:
if (!valParser.Parse(pp, pcntdn))
return false;
dscrLen = *((uint8_t*)theBuffer.pValue);
dscrType = *((uint8_t*)theBuffer.pValue + 1);
stateParseDescr = 2;
case 2:
// This is a sort of hack. Assuming that two bytes are already in the buffer
// the pointer is positioned two bytes ahead in order for the rest of descriptor
// to be read right after the size and the type fields.
// This should be used carefuly. varBuffer should be used directly to handle data
// in the buffer.
theBuffer.pValue = varBuffer + 2;
stateParseDescr = 3;
case 3:
switch (dscrType)
{
case USB_DESCRIPTOR_INTERFACE:
isGoodInterface = false;
case USB_DESCRIPTOR_CONFIGURATION:
theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2;
break;
case USB_DESCRIPTOR_ENDPOINT:
theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2;
break;
case HID_DESCRIPTOR_HID:
theBuffer.valueSize = dscrLen - 2;
break;
}
valParser.Initialize(&theBuffer);
stateParseDescr = 4;
case 4:
switch (dscrType)
{
case USB_DESCRIPTOR_CONFIGURATION:
if (!valParser.Parse(pp, pcntdn))
return false;
confValue = ((USB_CONFIGURATION_DESCRIPTOR*)varBuffer)->bConfigurationValue;
break;
case USB_DESCRIPTOR_INTERFACE:
if (!valParser.Parse(pp, pcntdn))
return false;
if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceClass != CLASS_ID)
break;
if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceSubClass != SUBCLASS_ID)
break;
if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol != PROTOCOL_ID)
break;
isGoodInterface = true;
ifaceNumber = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceNumber;
ifaceAltSet = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bAlternateSetting;
protoValue = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol;
break;
case USB_DESCRIPTOR_ENDPOINT:
if (!valParser.Parse(pp, pcntdn))
return false;
if (isGoodInterface)
if (theXtractor)
theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
break;
//case HID_DESCRIPTOR_HID:
// if (!valParser.Parse(pp, pcntdn))
// return false;
// PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
// break;
default:
if (!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
return false;
}
theBuffer.pValue = varBuffer;
stateParseDescr = 0;
}
return true;
}
/**
* \brief Print HID descriptor.
*
* \note TRACE_USBHOST macro must be enabled. See Usb.h for reference.
*
* \param pDesc Pointer to HID descriptor.
*/
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)
{
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescLength: %d\r\n", pDesc->bLength);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescriptorType: %d\r\n", pDesc->bDescriptorType);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bcdHID: %d\r\n", pDesc->bcdHID);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bCountryCode: %d\r\n", pDesc->bCountryCode);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bNumDescriptors: %d\r\n", pDesc->bNumDescriptors);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescrType: %d\r\n", pDesc->bDescrType);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : wDescriptorLength: %d\r\n", pDesc->wDescriptorLength);)
for (uint32_t i = 0; i < pDesc->bNumDescriptors; ++i)
{
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescrType: %d\r\n", pLT[i].bDescrType);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : wDescriptorLength: %d\r\n", pLT[i].wDescriptorLength);)
}
}
#endif /* CONFDESCPARSER_H_INCLUDED */

View File

@@ -1,70 +0,0 @@
/*
ADK Terminal Test
This demonstrates USB Host connectivity between an
Android phone and an Arduino Due.
The ADK for the Arduino Due is a work in progress
For additional information on the Arduino ADK visit
http://labs.arduino.cc/ADK/Index
created 27 June 2012
by Cristian Maglie
*/
#include "variant.h"
#include <stdio.h>
#include <adk.h>
// Accessory descriptor. It's how Arduino identifies itself to Android.
char applicationName[] = "Arduino_Terminal"; // the app on your phone
char accessoryName[] = "Arduino Due"; // your Arduino board
char companyName[] = "Arduino SA";
// Make up anything you want for these
char versionNumber[] = "1.0";
char serialNumber[] = "1";
char url[] = "http://labs.arduino.cc/uploads/ADK/ArduinoTerminal/ThibaultTerminal_ICS_0001.apk";
USBHost Usb;
ADK adk(&Usb, companyName, applicationName, accessoryName,versionNumber,url,serialNumber);
void setup()
{
cpu_irq_enable();
printf("\r\nADK demo start\r\n");
delay(200);
}
#define RCVSIZE 128
void loop()
{
uint8_t buf[RCVSIZE];
uint32_t nbread = 0;
char helloworld[] = "Hello World!\r\n";
Usb.Task();
if (adk.isReady())
{
/* Write hello string to ADK */
adk.write(strlen(helloworld), (uint8_t *)helloworld);
delay(1000);
/* Read data from ADK and print to UART */
adk.read(&nbread, RCVSIZE, buf);
if (nbread > 0)
{
printf("RCV: ");
for (uint32_t i = 0; i < nbread; ++i)
{
printf("%c", (char)buf[i]);
}
printf("\r\n");
}
}
}

View File

@@ -1,83 +0,0 @@
/*
Keyboard Controller Example
Shows the output of a USB Keyboard connected to
the Native USB port on an Arduino Due Board.
created 8 Oct 2012
by Cristian Maglie
http://arduino.cc/en/Tutorial/KeyboardController
This sample code is part of the public domain.
*/
// Require keyboard control library
#include <KeyboardController.h>
// Initialize USB Controller
USBHost usb;
// Attach keyboard controller to USB
KeyboardController keyboard(usb);
// This function intercepts key press
void keyPressed() {
Serial.print("Pressed: ");
printKey();
}
// This function intercepts key release
void keyReleased() {
Serial.print("Released: ");
printKey();
}
void printKey() {
// getOemKey() returns the OEM-code associated with the key
Serial.print(" key:");
Serial.print(keyboard.getOemKey());
// getModifiers() returns a bits field with the modifiers-keys
int mod = keyboard.getModifiers();
Serial.print(" mod:");
Serial.print(mod);
Serial.print(" => ");
if (mod & LeftCtrl)
Serial.print("L-Ctrl ");
if (mod & LeftShift)
Serial.print("L-Shift ");
if (mod & Alt)
Serial.print("Alt ");
if (mod & LeftCmd)
Serial.print("L-Cmd ");
if (mod & RightCtrl)
Serial.print("R-Ctrl ");
if (mod & RightShift)
Serial.print("R-Shift ");
if (mod & AltGr)
Serial.print("AltGr ");
if (mod & RightCmd)
Serial.print("R-Cmd ");
// getKey() returns the ASCII translation of OEM key
// combined with modifiers.
Serial.write(keyboard.getKey());
Serial.println();
}
void setup()
{
Serial.begin(9600);
Serial.println("Program started");
delay(200);
}
void loop()
{
// Process USB tasks
usb.Task();
}

View File

@@ -1,93 +0,0 @@
/*
Mouse Controller Example
Shows the output of a USB Mouse connected to
the Native USB port on an Arduino Due Board.
created 8 Oct 2012
by Cristian Maglie
http://arduino.cc/en/Tutorial/MouseController
This sample code is part of the public domain.
*/
// Require mouse control library
#include <MouseController.h>
// Initialize USB Controller
USBHost usb;
// Attach mouse controller to USB
MouseController mouse(usb);
// variables for mouse button states
boolean leftButton = false;
boolean middleButton = false;
boolean rightButton = false;
// This function intercepts mouse movements
void mouseMoved() {
Serial.print("Move: ");
Serial.print(mouse.getXChange());
Serial.print(", ");
Serial.println(mouse.getYChange());
}
// This function intercepts mouse movements while a button is pressed
void mouseDragged() {
Serial.print("DRAG: ");
Serial.print(mouse.getXChange());
Serial.print(", ");
Serial.println(mouse.getYChange());
}
// This function intercepts mouse button press
void mousePressed() {
Serial.print("Pressed: ");
if (mouse.getButton(LEFT_BUTTON)){
Serial.print("L");
leftButton = true;
}
if (mouse.getButton(MIDDLE_BUTTON)){
Serial.print("M");
middleButton = true;
}
if (mouse.getButton(RIGHT_BUTTON)){
Serial.print("R");
Serial.println();
rightButton = true;
}
}
// This function intercepts mouse button release
void mouseReleased() {
Serial.print("Released: ");
if (!mouse.getButton(LEFT_BUTTON) && leftButton == true) {
Serial.print("L");
leftButton = false;
}
if (!mouse.getButton(MIDDLE_BUTTON) && middleButton == true) {
Serial.print("M");
middleButton = false;
}
if (!mouse.getButton(RIGHT_BUTTON) && rightButton == true) {
Serial.print("R");
rightButton = false;
}
Serial.println();
}
void setup()
{
Serial.begin(9600);
Serial.println("Program started");
delay(200);
}
void loop()
{
// Process USB tasks
usb.Task();
}

View File

@@ -1,202 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#ifndef HID_H_INCLUDED
#define HID_H_INCLUDED
#include <stdint.h>
#include "usb_ch9.h"
#include "Usb.h"
#include "Arduino.h"
#include "confdescparser.h"
#include "hidusagestr.h"
#define DATA_SIZE_MASK 0x03
#define TYPE_MASK 0x0C
#define TAG_MASK 0xF0
#define DATA_SIZE_0 0x00
#define DATA_SIZE_1 0x01
#define DATA_SIZE_2 0x02
#define DATA_SIZE_4 0x03
#define TYPE_MAIN 0x00
#define TYPE_GLOBAL 0x04
#define TYPE_LOCAL 0x08
#define TAG_MAIN_INPUT 0x80
#define TAG_MAIN_OUTPUT 0x90
#define TAG_MAIN_COLLECTION 0xA0
#define TAG_MAIN_FEATURE 0xB0
#define TAG_MAIN_ENDCOLLECTION 0xC0
#define TAG_GLOBAL_USAGEPAGE 0x00
#define TAG_GLOBAL_LOGICALMIN 0x10
#define TAG_GLOBAL_LOGICALMAX 0x20
#define TAG_GLOBAL_PHYSMIN 0x30
#define TAG_GLOBAL_PHYSMAX 0x40
#define TAG_GLOBAL_UNITEXP 0x50
#define TAG_GLOBAL_UNIT 0x60
#define TAG_GLOBAL_REPORTSIZE 0x70
#define TAG_GLOBAL_REPORTID 0x80
#define TAG_GLOBAL_REPORTCOUNT 0x90
#define TAG_GLOBAL_PUSH 0xA0
#define TAG_GLOBAL_POP 0xB0
#define TAG_LOCAL_USAGE 0x00
#define TAG_LOCAL_USAGEMIN 0x10
#define TAG_LOCAL_USAGEMAX 0x20
/* HID requests */
#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
/* HID constants. Not part of chapter 9 */
/* Class-Specific Requests */
#define HID_REQUEST_GET_REPORT 0x01
#define HID_REQUEST_GET_IDLE 0x02
#define HID_REQUEST_GET_PROTOCOL 0x03
#define HID_REQUEST_SET_REPORT 0x09
#define HID_REQUEST_SET_IDLE 0x0A
#define HID_REQUEST_SET_PROTOCOL 0x0B
/* Class Descriptor Types */
#define HID_DESCRIPTOR_HID 0x21
#define HID_DESCRIPTOR_REPORT 0x22
#define HID_DESRIPTOR_PHY 0x23
/* Protocol Selection */
#define HID_BOOT_PROTOCOL 0x00
#define HID_RPT_PROTOCOL 0x01
/* HID Interface Class Code */
#define HID_INTF 0x03
/* HID Interface Class SubClass Codes */
#define HID_BOOT_INTF_SUBCLASS 0x01
/* HID Interface Class Protocol Codes */
#define HID_PROTOCOL_NONE 0x00
#define HID_PROTOCOL_KEYBOARD 0x01
#define HID_PROTOCOL_MOUSE 0x02
/**
* \brief HidItemPrefix definition.
*/
struct HidItemPrefix // Not used
{
uint8_t bSize : 2;
uint8_t bType : 2;
uint8_t bTag : 4;
};
#define HID_ITEM_TYPE_MAIN 0
#define HID_ITEM_TYPE_GLOBAL 1
#define HID_ITEM_TYPE_LOCAL 2
#define HID_ITEM_TYPE_RESERVED 3
#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value
#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask
#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value
#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value
#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value
#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value
#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value
#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0
#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1
#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2
#define HID_MAIN_ITEM_COLLECTION_REPORT 3
#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4
#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5
#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6
/**
* \brief MainItemIOFeature definition.
*/
struct MainItemIOFeature // Not used
{
uint8_t bmIsConstantOrData : 1;
uint8_t bmIsArrayOrVariable : 1;
uint8_t bmIsRelativeOrAbsolute : 1;
uint8_t bmIsWrapOrNoWrap : 1;
uint8_t bmIsNonLonearOrLinear : 1;
uint8_t bmIsNoPreferedOrPrefered : 1;
uint8_t bmIsNullOrNoNull : 1;
uint8_t bmIsVolatileOrNonVolatile : 1;
};
class HID;
/**
* \class Abstract HIDReportParser definition.
*
* \note This class is used to implement HID report parsing.
*/
class HIDReportParser
{
public:
virtual void Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf) = 0;
};
#define MAX_REPORT_PARSERS 2
#define HID_MAX_HID_CLASS_DESCRIPTORS 5
/**
* \class HID definition.
*/
class HID : public USBDeviceConfig, public UsbConfigXtracter
{
protected:
USBHost *pUsb; // USB class instance pointer
uint32_t bAddress; // address
protected:
static const uint32_t epInterruptInIndex = 1; // InterruptIN endpoint index
static const uint32_t epInterruptOutIndex = 2; // InterruptOUT endpoint index
static const uint32_t maxHidInterfaces = 3;
static const uint32_t maxEpPerInterface = 2;
static const uint32_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1);
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
virtual HIDReportParser* GetReportParser(uint32_t id) { return 0; };
public:
HID(USBHost *pusb) : pUsb(pusb) {};
const USBHost* GetUsb() { return pUsb; };
virtual bool SetReportParser(uint32_t id, HIDReportParser *prs) { return false; };
uint32_t SetProtocol(uint32_t iface, uint32_t protocol);
uint32_t GetProtocol(uint32_t iface, uint8_t* dataptr);
uint32_t GetIdle(uint32_t iface, uint32_t reportID, uint8_t* dataptr);
uint32_t SetIdle(uint32_t iface, uint32_t reportID, uint32_t duration);
uint32_t GetReportDescr(uint32_t ep, USBReadParser *parser = NULL);
uint32_t GetHidDescr(uint32_t ep, uint32_t nbytes, uint8_t* dataptr);
uint32_t GetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr);
uint32_t SetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr);
};
#endif /* HID_H_INCLUDED */

View File

@@ -1,141 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#include "hid.h"
/**
* \brief Get HID report descriptor and parse it.
*
* \param ep USB device endpoint.
* \param parser Parser used to decode report.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::GetReportDescr(uint32_t ep, USBReadParser *parser)
{
const uint32_t constBufLen = 64;
uint8_t buf[constBufLen];
return (pUsb->ctrlReq(bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser));
}
/**
* \brief Set HID report descriptor.
*
* \param ep USB device endpoint.
* \param iface Interface number.
* \param report_type HID report type.
* \param report_id HID report ID.
* \param nbytes Buffer length.
* \param dataptr Buffer containing the HID report to send.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::SetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr)
{
return (pUsb->ctrlReq(bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
}
/**
* \brief Get HID report descriptor.
*
* \param ep USB device endpoint.
* \param iface Interface number.
* \param report_type HID report type.
* \param report_id HID report ID.
* \param nbytes Buffer length.
* \param dataptr Buffer containing the HID report to send.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::GetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr)
{
return (pUsb->ctrlReq(bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
}
/**
* \brief Get HID idle status.
*
* \param iface Interface number.
* \param report_id HID report ID.
* \param dataptr Buffer to receive data. Size must be >= 1.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::GetIdle(uint32_t iface, uint32_t report_id, uint8_t* dataptr)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, report_id, 0, iface, 0x0001, 0x0001, dataptr, NULL));
}
/**
* \brief Set HID idle status.
*
* \param iface Interface number.
* \param report_id HID report ID.
* \param duration Status duration.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::SetIdle(uint32_t iface, uint32_t report_id, uint32_t duration)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, report_id, duration, iface, 0x0000, 0x0000, NULL, NULL));
}
/**
* \brief Set HID protocol.
*
* \param iface Interface number.
* \param protocol Protocol value.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::SetProtocol(uint32_t iface, uint32_t protocol)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL));
}
/**
* \brief Get HID protocol.
*
* \param iface Interface number.
* \param dataptr Buffer used to store protocol value. Size must be >= 1.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::GetProtocol(uint32_t iface, uint8_t* dataptr)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL));
}
/**
* \brief Print HID descriptor.
*
* \note TRACE_USBHOST macro must be enabled. See Usb.h for reference.
*
* \param pDesc Pointer to HID descriptor.
*/
void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)
{
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bDescLength: %d\r\n", pDesc->bLength);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bDescriptorType: %d\r\n", pDesc->bDescriptorType);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bcdHID: %d\r\n", pDesc->bcdHID);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bCountryCode: %d\r\n", pDesc->bCountryCode);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bNumDescriptors: %d\r\n", pDesc->bNumDescriptors);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bDescrType: %d\r\n", pDesc->bDescrType);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : wDescriptorLength: %d\r\n", pDesc->wDescriptorLength);)
}

View File

@@ -1,192 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#include "hidboot.h"
/**
* \brief Parse HID mouse report.
*
* \param hid HID device pointer.
* \param is_rpt_id True if this is a report ID.
* \param len Buffer length.
* \param buf Buffer containing report data.
*/
void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf)
{
MOUSEINFO *pmi = (MOUSEINFO*)buf;
if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1)
OnLeftButtonDown(pmi);
if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0)
OnLeftButtonUp(pmi);
if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1)
OnRightButtonDown(pmi);
if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0)
OnRightButtonUp(pmi);
if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1)
OnMiddleButtonDown(pmi);
if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0)
OnMiddleButtonUp(pmi);
if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY)
OnMouseMove(pmi);
for (uint32_t i = 0; i < 3; ++i)
prevState.bInfo[i] = buf[i];
};
/**
* \brief Parse HID keyboard report.
*
* \param hid HID device pointer.
* \param is_rpt_id True if this is a report ID.
* \param len Buffer length.
* \param buf Buffer containing report data.
*/
void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf)
{
// On error - return
if (buf[2] == 1)
return;
//KBDINFO *pki = (KBDINFO*)buf;
for (uint32_t i = 2; i < 8; ++i)
{
bool down = false;
bool up = false;
for (uint8_t j=2; j<8; j++)
{
if (buf[i] == prevState.bInfo[j] && buf[i] != 1)
down = true;
if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1)
up = true;
}
if (!down)
{
HandleLockingKeys(hid, buf[i]);
OnKeyDown(*buf, buf[i]);
}
if (!up)
OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]);
}
for (uint32_t i = 0; i < 8; ++i)
prevState.bInfo[i] = buf[i];
};
/**
* \brief Handle keyboard locking keys and manage keyboard leds using USB
* report.
*
* \param hid HID device pointer.
* \param key Locking key.
*
* \return 0 on success, error code otherwise.
*/
uint8_t KeyboardReportParser::HandleLockingKeys(HID *hid, uint8_t key)
{
uint8_t old_keys = kbdLockingKeys.bLeds;
switch (key)
{
case KEY_NUM_LOCK:
kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;
break;
case KEY_CAPS_LOCK:
kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock;
break;
case KEY_SCROLL_LOCK:
kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock;
break;
}
if (old_keys != kbdLockingKeys.bLeds && hid)
return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds));
return 0;
}
const uint8_t KeyboardReportParser::numKeys[] = { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')' };
const uint8_t KeyboardReportParser::symKeysUp[] = { '_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?' };
const uint8_t KeyboardReportParser::symKeysLo[] = { '-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/' };
const uint8_t KeyboardReportParser::padKeys[] = { '/', '*', '-', '+', 0x13 };
/**
* \brief Manage keyboard OEM to ASCII conversion.
*
* \param mod Keyboard modifier.
* \param key Key value to convert.
*
* \return Keyboard corresponding ASCII value on success, 0 otherwise.
*/
uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key)
{
uint8_t shift = (mod & 0x22);
// [a-z]
if (key > 0x03 && key < 0x1e)
{
// Upper case letters
if ( (kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) ||
(kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0) )
return (key - 4 + 'A');
// Lower case letters
else
return (key - 4 + 'a');
}
// Numbers
else if (key > 0x1d && key < 0x27)
{
if (shift)
return (numKeys[key - 0x1e]);
else
return (key - 0x1e + '1');
}
// Keypad Numbers
else if (key > 0x58 && key < 0x62)
{
if (kbdLockingKeys.kbdLeds.bmNumLock == 1)
return (key - 0x59 + '1');
}
else if (key > 0x2c && key < 0x39)
return ((shift) ? symKeysUp[key-0x2d] : symKeysLo[key-0x2d]);
else if (key > 0x53 && key < 0x59)
return padKeys[key - 0x54];
else
{
switch (key)
{
case KEY_SPACE: return (0x20);
case KEY_ENTER: return (0x13);
case KEY_ZERO: return ((shift) ? ')' : '0');
case KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0' : 0);
case KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.' : 0);
}
}
return 0;
}

View File

@@ -1,553 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#ifndef HIDBOOT_H_INCLUDED
#define HIDBOOT_H_INCLUDED
#include <stdint.h>
#include "usb_ch9.h"
#include "Usb.h"
#include "hid.h"
#include "Arduino.h"
#include "confdescparser.h"
#define KEY_SPACE 0x2c
#define KEY_ZERO 0x27
#define KEY_ZERO2 0x62
#define KEY_ENTER 0x28
#define KEY_PERIOD 0x63
/**
* \brief MOUSEINFO definition.
*/
struct MOUSEINFO
{
struct
{
uint8_t bmLeftButton : 1;
uint8_t bmRightButton : 1;
uint8_t bmMiddleButton : 1;
uint8_t bmDummy : 1;
};
int8_t dX;
int8_t dY;
};
/**
* \class MouseReportParser definition.
*/
class MouseReportParser : public HIDReportParser
{
union
{
MOUSEINFO mouseInfo;
uint8_t bInfo[3];
} prevState;
public:
virtual void Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf);
protected:
virtual void OnMouseMove (MOUSEINFO *mi) {};
virtual void OnLeftButtonUp (MOUSEINFO *mi) {};
virtual void OnLeftButtonDown (MOUSEINFO *mi) {};
virtual void OnRightButtonUp (MOUSEINFO *mi) {};
virtual void OnRightButtonDown (MOUSEINFO *mi) {};
virtual void OnMiddleButtonUp (MOUSEINFO *mi) {};
virtual void OnMiddleButtonDown (MOUSEINFO *mi) {};
};
/**
* \brief MODIFIERKEYS definition.
*/
struct MODIFIERKEYS
{
uint8_t bmLeftCtrl : 1;
uint8_t bmLeftShift : 1;
uint8_t bmLeftAlt : 1;
uint8_t bmLeftGUI : 1;
uint8_t bmRightCtrl : 1;
uint8_t bmRightShift : 1;
uint8_t bmRightAlt : 1;
uint8_t bmRightGUI : 1;
};
/**
* \brief KBDINFO definition.
*/
struct KBDINFO
{
struct
{
uint8_t bmLeftCtrl : 1;
uint8_t bmLeftShift : 1;
uint8_t bmLeftAlt : 1;
uint8_t bmLeftGUI : 1;
uint8_t bmRightCtrl : 1;
uint8_t bmRightShift : 1;
uint8_t bmRightAlt : 1;
uint8_t bmRightGUI : 1;
};
uint8_t bReserved;
uint8_t Keys[6];
};
/**
* \brief KBDLEDS definition.
*/
struct KBDLEDS
{
uint8_t bmNumLock : 1;
uint8_t bmCapsLock : 1;
uint8_t bmScrollLock : 1;
uint8_t bmCompose : 1;
uint8_t bmKana : 1;
uint8_t bmReserved : 3;
};
#define KEY_NUM_LOCK 0x53
// Clear compiler warning
#ifdef KEY_CAPS_LOCK
#undef KEY_CAPS_LOCK
#endif
#define KEY_CAPS_LOCK 0x39
#define KEY_SCROLL_LOCK 0x47
/**
* \class KeyboardReportParser definition.
*/
class KeyboardReportParser : public HIDReportParser
{
static const uint8_t numKeys[];
static const uint8_t symKeysUp[];
static const uint8_t symKeysLo[];
static const uint8_t padKeys[];
protected:
union
{
KBDINFO kbdInfo;
uint8_t bInfo[sizeof(KBDINFO)];
} prevState;
union
{
KBDLEDS kbdLeds;
uint8_t bLeds;
} kbdLockingKeys;
uint8_t OemToAscii(uint8_t mod, uint8_t key);
public:
KeyboardReportParser() { kbdLockingKeys.bLeds = 0; };
virtual void Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf);
protected:
uint8_t HandleLockingKeys(HID* hid, uint8_t key);
virtual void OnKeyDown (uint8_t mod, uint8_t key) {};
virtual void OnKeyUp (uint8_t mod, uint8_t key) {};
};
#define totalEndpoints 2
#define HID_MAX_HID_CLASS_DESCRIPTORS 5
/**
* \class HIDBoot definition.
*/
template <const uint8_t BOOT_PROTOCOL>
class HIDBoot : public HID
{
EpInfo epInfo[totalEndpoints];
HIDReportParser *pRptParser;
uint32_t bConfNum; // configuration number
uint32_t bIfaceNum; // Interface Number
uint32_t bNumIface; // number of interfaces in the configuration
uint32_t bNumEP; // total number of EP in the configuration
uint32_t qNextPollTime; // next poll time
bool bPollEnable; // poll enable flag
void Initialize();
virtual HIDReportParser* GetReportParser(uint32_t id) { return pRptParser; };
public:
HIDBoot(USBHost *p);
virtual bool SetReportParser(uint32_t id, HIDReportParser *prs) { pRptParser = prs; return true; };
// USBDeviceConfig implementation
virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
virtual uint32_t Release();
virtual uint32_t Poll();
virtual uint32_t GetAddress() { return bAddress; };
// UsbConfigXtracter implementation
virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
};
/**
* \brief HIDBoot class constructor.
*/
template <const uint8_t BOOT_PROTOCOL>
HIDBoot<BOOT_PROTOCOL>::HIDBoot(USBHost *p) :
HID(p),
pRptParser(NULL),
qNextPollTime(0),
bPollEnable(false)
{
Initialize();
if (pUsb)
pUsb->RegisterDeviceClass(this);
}
/**
* \brief Initialize HIDBoot class.
*/
template <const uint8_t BOOT_PROTOCOL>
void HIDBoot<BOOT_PROTOCOL>::Initialize()
{
for (uint32_t i = 0; i < totalEndpoints; ++i)
{
epInfo[i].deviceEpNum = 0;
epInfo[i].hostPipeNum = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
bNumEP = 1;
bNumIface = 0;
bConfNum = 0;
}
/**
* \brief Initialize connection to an HID device.
*
* \param parent USB device address of the Parent device.
* \param port USB device base address.
* \param lowspeed USB device speed.
*
* \return 0 on success, error code otherwise.
*/
template <const uint8_t BOOT_PROTOCOL>
uint32_t HIDBoot<BOOT_PROTOCOL>::Init(uint32_t parent, uint32_t port, uint32_t lowspeed)
{
const uint32_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR);
uint8_t buf[constBufSize];
uint32_t rcode = 0;
UsbDevice *p = 0;
EpInfo *oldep_ptr = 0;
uint32_t len = 0;
uint32_t num_of_conf = 0; // number of configurations
AddressPool &addrPool = pUsb->GetAddressPool();
TRACE_USBHOST(printf("HIDBoot::Init\r\n");)
if (bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0);
if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo)
{
TRACE_USBHOST(printf("HIDBoot::Init : epinfo is null!\r\n");)
return USB_ERROR_EPINFO_IS_NULL;
}
// Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo;
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo;
p->lowspeed = lowspeed;
// Get device descriptor
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
if (!rcode)
len = (buf[0] > constBufSize) ? constBufSize : buf[0];
if (rcode)
{
// Restore p->epinfo
p->epinfo = oldep_ptr;
goto FailGetDevDescr;
}
// Restore p->epinfo
p->epinfo = oldep_ptr;
// Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode)
{
p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
TRACE_USBHOST(printf("HIDBoot::Init : setAddr failed with rcode %lu\r\n", rcode);)
return rcode;
}
TRACE_USBHOST(printf("HIDBoot::Init : device address is now %lu\r\n", bAddress);)
p->lowspeed = false;
p = addrPool.GetUsbDevicePtr(bAddress);
if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed;
if (len)
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
if(rcode)
goto FailGetDevDescr;
num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
// Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode)
goto FailSetDevTblEntry;
TRACE_USBHOST(printf("HIDBoot::Init : number of configuration is %lu\r\n", num_of_conf);)
for (uint32_t i = 0; i < num_of_conf; ++i)
{
ConfigDescParser<
USB_CLASS_HID,
HID_BOOT_INTF_SUBCLASS,
BOOT_PROTOCOL,
CP_MASK_COMPARE_ALL> confDescrParser(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
if (bNumEP > 1)
break;
}
if (bNumEP < 2)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
TRACE_USBHOST(printf("HIDBoot::Init : bAddress: %lu\r\n", bAddress);)
TRACE_USBHOST(printf("HIDBoot::Init : bNumEP: %lu\r\n", bNumEP);)
// Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
TRACE_USBHOST(printf("HIDBoot::Init : bConfNum: %lu\r\n", bConfNum);)
// Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode)
goto FailSetConfDescr;
TRACE_USBHOST(printf("HIDBoot::Init : bIfaceNum: %lu\r\n", bIfaceNum);)
rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL);
if (rcode)
goto FailSetProtocol;
if (BOOT_PROTOCOL == 1)
{
rcode = SetIdle(bIfaceNum, 0, 0);
if (rcode)
goto FailSetIdle;
}
TRACE_USBHOST(printf("HIDBoot::Init : HID device configured successfully\r\n");)
bPollEnable = true;
return 0;
FailGetDevDescr:
TRACE_USBHOST(printf("HIDBoot::Init getDevDescr : ");)
goto Fail;
FailSetDevTblEntry:
TRACE_USBHOST(printf("HIDBoot::Init setDevTblEn : ");)
goto Fail;
FailSetProtocol:
TRACE_USBHOST(printf("HIDBoot::Init SetProto : ");)
goto Fail;
FailSetIdle:
TRACE_USBHOST(printf("HIDBoot::Init SetIdle : ");)
goto Fail;
FailSetConfDescr:
TRACE_USBHOST(printf("HIDBoot::Init setConf : ");)
goto Fail;
Fail:
TRACE_USBHOST(printf("error code: %lu\r\n", rcode);)
Release();
return rcode;
}
/**
* \brief Extract interrupt-IN endpoint information from configuration
* descriptor.
*
* \param conf Configuration number.
* \param iface Interface number.
* \param alt Alternate setting.
* \param proto Protocol version used.
* \param pep Pointer to endpoint descriptor.
*/
template <const uint8_t BOOT_PROTOCOL>
void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
{
// If the first configuration satisfies, the others are not considered.
if (bNumEP > 1 && conf != bConfNum)
return;
bConfNum = conf;
bIfaceNum = iface;
uint32_t index = 0;
uint32_t pipe = 0;
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
{
index = epInterruptInIndex;
// Fill in the endpoint info structure
epInfo[index].deviceEpNum = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0;
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : Found new endpoint\r\n");)
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : deviceEpNum: %lu\r\n", epInfo[index].deviceEpNum);)
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : maxPktSize: %lu\r\n", epInfo[index].maxPktSize);)
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : index: %lu\r\n", index);)
// Ensure pipe allocation is okay
pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_INTRPT, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 10, UOTGHS_HSTPIPCFG_PBK_1_BANK);
if (pipe == 0)
{
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : Pipe allocation failure\r\n");)
// Enumeration failed
return;
}
epInfo[index].hostPipeNum = pipe;
bNumEP++;
}
}
/**
* \brief Release USB allocated resources (pipes and address).
*
* \note Release call is made from USBHost.task() on disconnection events.
* \note Release call is made from Init() on enumeration failure.
*
* \return Always 0.
*/
template <const uint8_t BOOT_PROTOCOL>
uint32_t HIDBoot<BOOT_PROTOCOL>::Release()
{
// Free allocated host pipes
UHD_Pipe_Free(epInfo[epInterruptInIndex].hostPipeNum);
// Free allocated USB address
pUsb->GetAddressPool().FreeAddress(bAddress);
bConfNum = 0;
bIfaceNum = 0;
bNumEP = 1;
bAddress = 0;
qNextPollTime = 0;
bPollEnable = false;
return 0;
}
/**
* \brief Poll USB device activity.
*
* \note Poll call is periodically made from USBHost.task().
*
* \return 0 on success, error code otherwise.
*/
template <const uint8_t BOOT_PROTOCOL>
uint32_t HIDBoot<BOOT_PROTOCOL>::Poll()
{
uint32_t rcode = 0;
if (!bPollEnable)
return 0;
if (qNextPollTime <= millis())
{
qNextPollTime = millis() + 10;
const uint32_t const_buff_len = 16;
uint8_t buf[const_buff_len];
uint32_t read = epInfo[epInterruptInIndex].maxPktSize;
rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].deviceEpNum, &read, buf);
if (rcode)
{
return rcode;
}
if (pRptParser)
pRptParser->Parse((HID*)this, 0, (uint32_t)read, buf);
}
return rcode;
}
#endif /* HIDBOOT_H_INCLUDED */

View File

@@ -1,976 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#ifndef HIDUSAGESTR_H_INCLUDED
#define HIDUSAGESTR_H_INCLUDED
const char pstrSpace [] = " ";
const char pstrCRLF [] = "\r\n";
const char pstrSingleTab [] = "\t";
const char pstrDoubleTab [] = "\t\t";
const char pstrTripleTab [] = "\t\t\t";
// Usage Page String Titles
const char pstrUsagePageUndefined [] = "Undef";
const char pstrUsagePageGenericDesktopControls [] = "Gen Desktop Ctrls";
const char pstrUsagePageSimulationControls [] = "Simu Ctrls";
const char pstrUsagePageVRControls [] = "VR Ctrls";
const char pstrUsagePageSportControls [] = "Sport Ctrls";
const char pstrUsagePageGameControls [] = "Game Ctrls";
const char pstrUsagePageGenericDeviceControls [] = "Gen Dev Ctrls";
const char pstrUsagePageKeyboardKeypad [] = "Kbrd/Keypad";
const char pstrUsagePageLEDs [] = "LEDs";
const char pstrUsagePageButton [] = "Button";
const char pstrUsagePageOrdinal [] = "Ordinal";
const char pstrUsagePageTelephone [] = "Tel";
const char pstrUsagePageConsumer [] = "Consumer";
const char pstrUsagePageDigitizer [] = "Digitizer";
const char pstrUsagePagePID [] = "PID";
const char pstrUsagePageUnicode [] = "Unicode";
const char pstrUsagePageAlphaNumericDisplay [] = "Alpha Num Disp";
const char pstrUsagePageMedicalInstruments [] = "Medical Instr";
const char pstrUsagePageMonitor [] = "Monitor";
const char pstrUsagePagePower [] = "Power";
const char pstrUsagePageBarCodeScanner [] = "Bar Code Scan";
const char pstrUsagePageScale [] = "Scale";
const char pstrUsagePageMSRDevices [] = "Magn Stripe Read Dev";
const char pstrUsagePagePointOfSale [] = "POS";
const char pstrUsagePageCameraControl [] = "Cam Ctrl";
const char pstrUsagePageArcade [] = "Arcade";
const char pstrUsagePageReserved [] = "Reserved";
const char pstrUsagePageVendorDefined [] = "Vendor Def";
// Generic Desktop Controls Page
const char pstrUsagePointer [] = "Pointer";
const char pstrUsageMouse [] = "Mouse";
const char pstrUsageJoystick [] = "Joystick";
const char pstrUsageGamePad [] = "Game Pad";
const char pstrUsageKeyboard [] = "Kbrd";
const char pstrUsageKeypad [] = "Keypad";
const char pstrUsageMultiAxisController [] = "Multi-axis Ctrl";
const char pstrUsageTabletPCSystemControls [] = "Tablet PC Sys Ctrls";
const char pstrUsageX [] = "X";
const char pstrUsageY [] = "Y";
const char pstrUsageZ [] = "Z";
const char pstrUsageRx [] = "Rx";
const char pstrUsageRy [] = "Ry";
const char pstrUsageRz [] = "Rz";
const char pstrUsageSlider [] = "Slider";
const char pstrUsageDial [] = "Dial";
const char pstrUsageWheel [] = "Wheel";
const char pstrUsageHatSwitch [] = "Hat Switch";
const char pstrUsageCountedBuffer [] = "Counted Buf";
const char pstrUsageByteCount [] = "Byte Count";
const char pstrUsageMotionWakeup [] = "Motion Wakeup";
const char pstrUsageStart [] = "Start";
const char pstrUsageSelect [] = "Sel";
const char pstrUsageVx [] = "Vx";
const char pstrUsageVy [] = "Vy";
const char pstrUsageVz [] = "Vz";
const char pstrUsageVbrx [] = "Vbrx";
const char pstrUsageVbry [] = "Vbry";
const char pstrUsageVbrz [] = "Vbrz";
const char pstrUsageVno [] = "Vno";
const char pstrUsageFeatureNotification [] = "Feature Notif";
const char pstrUsageResolutionMultiplier [] = "Res Mult";
const char pstrUsageSystemControl [] = "Sys Ctrl";
const char pstrUsageSystemPowerDown [] = "Sys Pwr Down";
const char pstrUsageSystemSleep [] = "Sys Sleep";
const char pstrUsageSystemWakeup [] = "Sys Wakeup";
const char pstrUsageSystemContextMenu [] = "Sys Context Menu";
const char pstrUsageSystemMainMenu [] = "Sys Main Menu";
const char pstrUsageSystemAppMenu [] = "Sys App Menu";
const char pstrUsageSystemMenuHelp [] = "Sys Menu Help";
const char pstrUsageSystemMenuExit [] = "Sys Menu Exit";
const char pstrUsageSystemMenuSelect [] = "Sys Menu Select";
const char pstrUsageSystemMenuRight [] = "Sys Menu Right";
const char pstrUsageSystemMenuLeft [] = "Sys Menu Left";
const char pstrUsageSystemMenuUp [] = "Sys Menu Up";
const char pstrUsageSystemMenuDown [] = "Sys Menu Down";
const char pstrUsageSystemColdRestart [] = "Sys Cold Restart";
const char pstrUsageSystemWarmRestart [] = "Sys Warm Restart";
const char pstrUsageDPadUp [] = "D-pad Up";
const char pstrUsageDPadDown [] = "D-pad Down";
const char pstrUsageDPadRight [] = "D-pad Right";
const char pstrUsageDPadLeft [] = "D-pad Left";
const char pstrUsageSystemDock [] = "Sys Dock";
const char pstrUsageSystemUndock [] = "Sys Undock";
const char pstrUsageSystemSetup [] = "Sys Setup";
const char pstrUsageSystemBreak [] = "Sys Break";
const char pstrUsageSystemDebuggerBreak [] = "Sys Dbg Brk";
const char pstrUsageApplicationBreak [] = "App Break";
const char pstrUsageApplicationDebuggerBreak [] = "App Dbg Brk";
const char pstrUsageSystemSpeakerMute [] = "Sys Spk Mute";
const char pstrUsageSystemHibernate [] = "Sys Hiber";
const char pstrUsageSystemDisplayInvert [] = "Sys Disp Inv";
const char pstrUsageSystemDisplayInternal [] = "Sys Disp Int";
const char pstrUsageSystemDisplayExternal [] = "Sys Disp Ext";
const char pstrUsageSystemDisplayBoth [] = "Sys Disp Both";
const char pstrUsageSystemDisplayDual [] = "Sys Disp Dual";
const char pstrUsageSystemDisplayToggleIntExt [] = "Sys Disp Tgl Int/Ext";
const char pstrUsageSystemDisplaySwapPriSec [] = "Sys Disp Swap Pri/Sec";
const char pstrUsageSystemDisplayLCDAutoscale [] = "Sys Disp LCD Autoscale";
// Simulation Controls Page
const char pstrUsageFlightSimulationDevice [] = "Flight Simu Dev";
const char pstrUsageAutomobileSimulationDevice [] = "Auto Simu Dev";
const char pstrUsageTankSimulationDevice [] = "Tank Simu Dev";
const char pstrUsageSpaceshipSimulationDevice [] = "Space Simu Dev";
const char pstrUsageSubmarineSimulationDevice [] = "Subm Simu Dev";
const char pstrUsageSailingSimulationDevice [] = "Sail Simu Dev";
const char pstrUsageMotocicleSimulationDevice [] = "Moto Simu Dev";
const char pstrUsageSportsSimulationDevice [] = "Sport Simu Dev";
const char pstrUsageAirplaneSimulationDevice [] = "Airp Simu Dev";
const char pstrUsageHelicopterSimulationDevice [] = "Heli Simu Dev";
const char pstrUsageMagicCarpetSimulationDevice [] = "Magic Carpet Simu Dev";
const char pstrUsageBicycleSimulationDevice [] = "Bike Simu Dev";
const char pstrUsageFlightControlStick [] = "Flight Ctrl Stick";
const char pstrUsageFlightStick [] = "Flight Stick";
const char pstrUsageCyclicControl [] = "Cyclic Ctrl";
const char pstrUsageCyclicTrim [] = "Cyclic Trim";
const char pstrUsageFlightYoke [] = "Flight Yoke";
const char pstrUsageTrackControl [] = "Track Ctrl";
const char pstrUsageAileron [] = "Aileron";
const char pstrUsageAileronTrim [] = "Aileron Trim";
const char pstrUsageAntiTorqueControl [] = "Anti-Torque Ctrl";
const char pstrUsageAutopilotEnable [] = "Autopilot Enable";
const char pstrUsageChaffRelease [] = "Chaff Release";
const char pstrUsageCollectiveControl [] = "Collective Ctrl";
const char pstrUsageDiveBrake [] = "Dive Brake";
const char pstrUsageElectronicCountermeasures [] = "El Countermeasures";
const char pstrUsageElevator [] = "Elevator";
const char pstrUsageElevatorTrim [] = "Elevator Trim";
const char pstrUsageRudder [] = "Rudder";
const char pstrUsageThrottle [] = "Throttle";
const char pstrUsageFlightCommunications [] = "Flight Comm";
const char pstrUsageFlareRelease [] = "Flare Release";
const char pstrUsageLandingGear [] = "Landing Gear";
const char pstrUsageToeBrake [] = "Toe Brake";
const char pstrUsageTrigger [] = "Trigger";
const char pstrUsageWeaponsArm [] = "Weapons Arm";
const char pstrUsageWeaponsSelect [] = "Weapons Sel";
const char pstrUsageWingFlaps [] = "Wing Flaps";
const char pstrUsageAccelerator [] = "Accel";
const char pstrUsageBrake [] = "Brake";
const char pstrUsageClutch [] = "Clutch";
const char pstrUsageShifter [] = "Shifter";
const char pstrUsageSteering [] = "Steering";
const char pstrUsageTurretDirection [] = "Turret Dir";
const char pstrUsageBarrelElevation [] = "Barrel Ele";
const char pstrUsageDivePlane [] = "Dive Plane";
const char pstrUsageBallast [] = "Ballast";
const char pstrUsageBicycleCrank [] = "Bicycle Crank";
const char pstrUsageHandleBars [] = "Handle Bars";
const char pstrUsageFrontBrake [] = "Front Brake";
const char pstrUsageRearBrake [] = "Rear Brake";
// VR Controls Page
const char pstrUsageBelt [] = "Belt";
const char pstrUsageBodySuit [] = "Body Suit";
const char pstrUsageFlexor [] = "Flexor";
const char pstrUsageGlove [] = "Glove";
const char pstrUsageHeadTracker [] = "Head Track";
const char pstrUsageHeadMountedDisplay [] = "Head Disp";
const char pstrUsageHandTracker [] = "Hand Track";
const char pstrUsageOculometer [] = "Oculometer";
const char pstrUsageVest [] = "Vest";
const char pstrUsageAnimatronicDevice [] = "Animat Dev";
const char pstrUsageStereoEnable [] = "Stereo Enbl";
const char pstrUsageDisplayEnable [] = "Display Enbl";
// Sport Controls Page
const char pstrUsageBaseballBat [] = "Baseball Bat";
const char pstrUsageGolfClub [] = "Golf Club";
const char pstrUsageRowingMachine [] = "Rowing Mach";
const char pstrUsageTreadmill [] = "Treadmill";
const char pstrUsageOar [] = "Oar";
const char pstrUsageSlope [] = "Slope";
const char pstrUsageRate [] = "Rate";
const char pstrUsageStickSpeed [] = "Stick Speed";
const char pstrUsageStickFaceAngle [] = "Stick Face Ang";
const char pstrUsageStickHeelToe [] = "Stick Heel/Toe";
const char pstrUsageStickFollowThough [] = "Stick Flw Thru";
const char pstrUsageStickTempo [] = "Stick Tempo";
const char pstrUsageStickType [] = "Stick Type";
const char pstrUsageStickHeight [] = "Stick Hght";
const char pstrUsagePutter [] = "Putter";
const char pstrUsage1Iron [] = "1 Iron";
const char pstrUsage2Iron [] = "2 Iron";
const char pstrUsage3Iron [] = "3 Iron";
const char pstrUsage4Iron [] = "4 Iron";
const char pstrUsage5Iron [] = "5 Iron";
const char pstrUsage6Iron [] = "6 Iron";
const char pstrUsage7Iron [] = "7 Iron";
const char pstrUsage8Iron [] = "8 Iron";
const char pstrUsage9Iron [] = "9 Iron";
const char pstrUsage10Iron [] = "10 Iron";
const char pstrUsage11Iron [] = "11 Iron";
const char pstrUsageSandWedge [] = "Sand Wedge";
const char pstrUsageLoftWedge [] = "Loft Wedge";
const char pstrUsagePowerWedge [] = "Pwr Wedge";
const char pstrUsage1Wood [] = "1 Wood";
const char pstrUsage3Wood [] = "3 Wood";
const char pstrUsage5Wood [] = "5 Wood";
const char pstrUsage7Wood [] = "7 Wood";
const char pstrUsage9Wood [] = "9 Wood";
// Game Controls Page
const char pstrUsage3DGameController [] = "3D Game Ctrl";
const char pstrUsagePinballDevice [] = "Pinball Dev";
const char pstrUsageGunDevice [] = "Gun Dev";
const char pstrUsagePointOfView [] = "POV";
const char pstrUsageTurnRightLeft [] = "Turn Right Left";
const char pstrUsagePitchForwardBackward [] = "Pitch Fwd/Back";
const char pstrUsageRollRightLeft [] = "Roll Right/Left";
const char pstrUsageMoveRightLeft [] = "Move Right/Left";
const char pstrUsageMoveForwardBackward [] = "Move Fwd/Back";
const char pstrUsageMoveUpDown [] = "Move Up/Down";
const char pstrUsageLeanRightLeft [] = "Lean Right/Left";
const char pstrUsageLeanForwardBackward [] = "Lean Fwd/Back";
const char pstrUsageHeightOfPOV [] = "Height of POV";
const char pstrUsageFlipper [] = "Flipper";
const char pstrUsageSecondaryFlipper [] = "Second Flipper";
const char pstrUsageBump [] = "Bump";
const char pstrUsageNewGame [] = "New Game";
const char pstrUsageShootBall [] = "Shoot Ball";
const char pstrUsagePlayer [] = "Player";
const char pstrUsageGunBolt [] = "Gun Bolt";
const char pstrUsageGunClip [] = "Gun Clip";
const char pstrUsageGunSelector [] = "Gun Sel";
const char pstrUsageGunSingleShot [] = "Gun Sngl Shot";
const char pstrUsageGunBurst [] = "Gun Burst";
const char pstrUsageGunAutomatic [] = "Gun Auto";
const char pstrUsageGunSafety [] = "Gun Safety";
const char pstrUsageGamepadFireJump [] = "Gamepad Fire/Jump";
const char pstrUsageGamepadTrigger [] = "Gamepad Trig";
// Generic Device Controls Page
const char pstrUsageBatteryStrength [] = "Bat Strength";
const char pstrUsageWirelessChannel [] = "Wireless Ch";
const char pstrUsageWirelessID [] = "Wireless ID";
const char pstrUsageDiscoverWirelessControl [] = "Discover Wireless Ctrl";
const char pstrUsageSecurityCodeCharEntered [] = "Sec Code Char Entrd";
const char pstrUsageSecurityCodeCharErased [] = "Sec Code Char Erased";
const char pstrUsageSecurityCodeCleared [] = "Sec Code Cleared";
// LED Page
const char pstrUsageNumLock [] = "Num Lock";
const char pstrUsageCapsLock [] = "Caps Lock";
const char pstrUsageScrollLock [] = "Scroll Lock";
const char pstrUsageCompose [] = "Compose";
const char pstrUsageKana [] = "Kana";
const char pstrUsagePower [] = "Pwr";
const char pstrUsageShift [] = "Shift";
const char pstrUsageDoNotDisturb [] = "DND";
const char pstrUsageMute [] = "Mute";
const char pstrUsageToneEnable [] = "Tone Enbl";
const char pstrUsageHighCutFilter [] = "High Cut Fltr";
const char pstrUsageLowCutFilter [] = "Low Cut Fltr";
const char pstrUsageEqualizerEnable [] = "Eq Enbl";
const char pstrUsageSoundFieldOn [] = "Sound Field On";
const char pstrUsageSurroundOn [] = "Surround On";
const char pstrUsageRepeat [] = "Repeat";
const char pstrUsageStereo [] = "Stereo";
const char pstrUsageSamplingRateDetect [] = "Smpl Rate Detect";
const char pstrUsageSpinning [] = "Spinning";
const char pstrUsageCAV [] = "CAV";
const char pstrUsageCLV [] = "CLV";
const char pstrUsageRecordingFormatDetect [] = "Rec Format Detect";
const char pstrUsageOffHook [] = "Off Hook";
const char pstrUsageRing [] = "Ring";
const char pstrUsageMessageWaiting [] = "Msg Wait";
const char pstrUsageDataMode [] = "Data Mode";
const char pstrUsageBatteryOperation [] = "Bat Op";
const char pstrUsageBatteryOK [] = "Bat OK";
const char pstrUsageBatteryLow [] = "Bat Low";
const char pstrUsageSpeaker [] = "Speaker";
const char pstrUsageHeadSet [] = "Head Set";
const char pstrUsageHold [] = "Hold";
const char pstrUsageMicrophone [] = "Mic";
const char pstrUsageCoverage [] = "Coverage";
const char pstrUsageNightMode [] = "Night Mode";
const char pstrUsageSendCalls [] = "Send Calls";
const char pstrUsageCallPickup [] = "Call Pickup";
const char pstrUsageConference [] = "Conf";
const char pstrUsageStandBy [] = "Stand-by";
const char pstrUsageCameraOn [] = "Cam On";
const char pstrUsageCameraOff [] = "Cam Off";
const char pstrUsageOnLine [] = "On-Line";
const char pstrUsageOffLine [] = "Off-Line";
const char pstrUsageBusy [] = "Busy";
const char pstrUsageReady [] = "Ready";
const char pstrUsagePaperOut [] = "Paper Out";
const char pstrUsagePaperJam [] = "Paper Jam";
const char pstrUsageRemote [] = "Remote";
const char pstrUsageForward [] = "Fwd";
const char pstrUsageReverse [] = "Rev";
const char pstrUsageStop [] = "Stop";
const char pstrUsageRewind [] = "Rewind";
const char pstrUsageFastForward [] = "Fast Fwd";
const char pstrUsagePlay [] = "Play";
const char pstrUsagePause [] = "Pause";
const char pstrUsageRecord [] = "Rec";
const char pstrUsageError [] = "Error";
const char pstrUsageSelectedIndicator [] = "Usage Sel Ind";
const char pstrUsageInUseIndicator [] = "Usage In Use Ind";
const char pstrUsageMultiModeIndicator [] = "Usage Multi Mode Ind";
const char pstrUsageIndicatorOn [] = "Ind On";
const char pstrUsageIndicatorFlash [] = "Ind Flash";
const char pstrUsageIndicatorSlowBlink [] = "Ind Slow Blk";
const char pstrUsageIndicatorFastBlink [] = "Ind Fast Blk";
const char pstrUsageIndicatorOff [] = "Ind Off";
const char pstrUsageFlashOnTime [] = "Flash On Time";
const char pstrUsageSlowBlinkOnTime [] = "Slow Blk On Time";
const char pstrUsageSlowBlinkOffTime [] = "Slow Blk Off Time";
const char pstrUsageFastBlinkOnTime [] = "Fast Blk On Time";
const char pstrUsageFastBlinkOffTime [] = "Fast Blk Off Time";
const char pstrUsageIndicatorColor [] = "Usage Ind Color";
const char pstrUsageIndicatorRed [] = "Ind Red";
const char pstrUsageIndicatorGreen [] = "Ind Green";
const char pstrUsageIndicatorAmber [] = "Ind Amber";
const char pstrUsageGenericIndicator [] = "Gen Ind";
const char pstrUsageSystemSuspend [] = "Sys Suspend";
const char pstrUsageExternalPowerConnected [] = "Ext Pwr Conn";
// Telephony Usage Page
const char pstrUsagePhone [] = "Phone";
const char pstrUsageAnsweringMachine [] = "Answ Mach";
const char pstrUsageMessageControls [] = "Msg Ctrls";
const char pstrUsageHandset [] = "Handset";
const char pstrUsageHeadset [] = "Headset";
const char pstrUsageTelephonyKeyPad [] = "Tel Key Pad";
const char pstrUsageProgrammableButton [] = "Prog Button";
const char pstrUsageHookSwitch [] = "Hook Sw";
const char pstrUsageFlash [] = "Flash";
const char pstrUsageFeature [] = "Feature";
//const char pstrUsageHold [] = "Hold";
const char pstrUsageRedial [] = "Redial";
const char pstrUsageTransfer [] = "Transfer";
const char pstrUsageDrop [] = "Drop";
const char pstrUsagePark [] = "Park";
const char pstrUsageForwardCalls [] = "Fwd Calls";
const char pstrUsageAlternateFunction [] = "Alt Func";
const char pstrUsageLine [] = "Line";
const char pstrUsageSpeakerPhone [] = "Spk Phone";
//const char pstrUsageConference [] = "Conference";
const char pstrUsageRingEnable [] = "Ring Enbl";
const char pstrUsageRingSelect [] = "Ring Sel";
const char pstrUsagePhoneMute [] = "Phone Mute";
const char pstrUsageCallerID [] = "Caller ID";
const char pstrUsageSend [] = "Send";
const char pstrUsageSpeedDial [] = "Speed Dial";
const char pstrUsageStoreNumber [] = "Store Num";
const char pstrUsageRecallNumber [] = "Recall Num";
const char pstrUsagePhoneDirectory [] = "Phone Dir";
const char pstrUsageVoiceMail [] = "Voice Mail";
const char pstrUsageScreenCalls [] = "Screen Calls";
//const char pstrUsageDoNotDisturb [] = "Do Not Disturb";
const char pstrUsageMessage [] = "Msg";
const char pstrUsageAnswerOnOff [] = "Answer On/Off";
const char pstrUsageInsideDialTone [] = "Inside Dial Tone";
const char pstrUsageOutsideDialTone [] = "Outside Dial Tone";
const char pstrUsageInsideRingTone [] = "Inside Ring Tone";
const char pstrUsageOutsideRingTone [] = "Outside Ring Tone";
const char pstrUsagePriorityRingTone [] = "Prior Ring Tone";
const char pstrUsageInsideRingback [] = "Inside Ringback";
const char pstrUsagePriorityRingback [] = "Priority Ringback";
const char pstrUsageLineBusyTone [] = "Ln Busy Tone";
const char pstrUsageReorderTone [] = "Reorder Tone";
const char pstrUsageCallWaitingTone [] = "Call Wait Tone";
const char pstrUsageConfirmationTone1 [] = "Cnfrm Tone1";
const char pstrUsageConfirmationTone2 [] = "Cnfrm Tone2";
const char pstrUsageTonesOff [] = "Tones Off";
const char pstrUsageOutsideRingback [] = "Outside Ringback";
const char pstrUsageRinger [] = "Ringer";
const char pstrUsagePhoneKey0 [] = "0";
const char pstrUsagePhoneKey1 [] = "1";
const char pstrUsagePhoneKey2 [] = "2";
const char pstrUsagePhoneKey3 [] = "3";
const char pstrUsagePhoneKey4 [] = "4";
const char pstrUsagePhoneKey5 [] = "5";
const char pstrUsagePhoneKey6 [] = "6";
const char pstrUsagePhoneKey7 [] = "7";
const char pstrUsagePhoneKey8 [] = "8";
const char pstrUsagePhoneKey9 [] = "9";
const char pstrUsagePhoneKeyStar [] = "*";
const char pstrUsagePhoneKeyPound [] = "#";
const char pstrUsagePhoneKeyA [] = "A";
const char pstrUsagePhoneKeyB [] = "B";
const char pstrUsagePhoneKeyC [] = "C";
const char pstrUsagePhoneKeyD [] = "D";
// Consumer Usage Page
const char pstrUsageConsumerControl [] = "Consumer Ctrl";
const char pstrUsageNumericKeyPad [] = "Num Key Pad";
//const char pstrUsageProgrammableButton [] = "Prog Btn";
//const char pstrUsageMicrophone [] = "Mic";
const char pstrUsageHeadphone [] = "Headphone";
const char pstrUsageGraphicEqualizer [] = "Graph Eq";
const char pstrUsagePlus10 [] = "+10";
const char pstrUsagePlus100 [] = "+100";
const char pstrUsageAMPM [] = "AM/PM";
//const char pstrUsagePower [] = "Pwr";
const char pstrUsageReset [] = "Reset";
const char pstrUsageSleep [] = "Sleep";
const char pstrUsageSleepAfter [] = "Sleep After";
const char pstrUsageSleepMode [] = "Sleep Mode";
const char pstrUsageIllumination [] = "Illumin";
const char pstrUsageFunctionButtons [] = "Func Btns";
const char pstrUsageMenu [] = "Menu";
const char pstrUsageMenuPick [] = "Menu Pick";
const char pstrUsageMenuUp [] = "Menu Up";
const char pstrUsageMenuDown [] = "Menu Down";
const char pstrUsageMenuLeft [] = "Menu Left";
const char pstrUsageMenuRight [] = "Menu Right";
const char pstrUsageMenuEscape [] = "Menu Esc";
const char pstrUsageMenuValueIncrease [] = "Menu Val Inc";
const char pstrUsageMenuValueDecrease [] = "Menu Val Dec";
const char pstrUsageDataOnScreen [] = "Data On Scr";
const char pstrUsageClosedCaption [] = "Closed Cptn";
const char pstrUsageClosedCaptionSelect [] = "Closed Cptn Sel";
const char pstrUsageVCRTV [] = "VCR/TV";
const char pstrUsageBroadcastMode [] = "Brdcast Mode";
const char pstrUsageSnapshot [] = "Snapshot";
const char pstrUsageStill [] = "Still";
const char pstrUsageSelection [] = "Sel";
const char pstrUsageAssignSelection [] = "Assign Sel";
const char pstrUsageModeStep [] = "Mode Step";
const char pstrUsageRecallLast [] = "Recall Last";
const char pstrUsageEnterChannel [] = "Entr Channel";
const char pstrUsageOrderMovie [] = "Ord Movie";
const char pstrUsageChannel [] = "Channel";
const char pstrUsageMediaSelection [] = "Med Sel";
const char pstrUsageMediaSelectComputer [] = "Med Sel Comp";
const char pstrUsageMediaSelectTV [] = "Med Sel TV";
const char pstrUsageMediaSelectWWW [] = "Med Sel WWW";
const char pstrUsageMediaSelectDVD [] = "Med Sel DVD";
const char pstrUsageMediaSelectTelephone [] = "Med Sel Tel";
const char pstrUsageMediaSelectProgramGuide [] = "Med Sel PG";
const char pstrUsageMediaSelectVideoPhone [] = "Med Sel Vid";
const char pstrUsageMediaSelectGames [] = "Med Sel Games";
const char pstrUsageMediaSelectMessages [] = "Med Sel Msg";
const char pstrUsageMediaSelectCD [] = "Med Sel CD";
const char pstrUsageMediaSelectVCR [] = "Med Sel VCR";
const char pstrUsageMediaSelectTuner [] = "Med Sel Tuner";
const char pstrUsageQuit [] = "Quit";
const char pstrUsageHelp [] = "Help";
const char pstrUsageMediaSelectTape [] = "Med Sel Tape";
const char pstrUsageMediaSelectCable [] = "Med Sel Cbl";
const char pstrUsageMediaSelectSatellite [] = "Med Sel Sat";
const char pstrUsageMediaSelectSecurity [] = "Med Sel Secur";
const char pstrUsageMediaSelectHome [] = "Med Sel Home";
const char pstrUsageMediaSelectCall [] = "Med Sel Call";
const char pstrUsageChannelIncrement [] = "Ch Inc";
const char pstrUsageChannelDecrement [] = "Ch Dec";
const char pstrUsageMediaSelectSAP [] = "Med Sel SAP";
const char pstrUsageVCRPlus [] = "VCR+";
const char pstrUsageOnce [] = "Once";
const char pstrUsageDaily [] = "Daily";
const char pstrUsageWeekly [] = "Weekly";
const char pstrUsageMonthly [] = "Monthly";
//const char pstrUsagePlay [] = "Play";
//const char pstrUsagePause [] = "Pause";
//const char pstrUsageRecord [] = "Rec";
//const char pstrUsageFastForward [] = "FF";
//const char pstrUsageRewind [] = "Rewind";
const char pstrUsageScanNextTrack [] = "Next Track";
const char pstrUsageScanPreviousTrack [] = "Prev Track";
//const char pstrUsageStop [] = "Stop";
const char pstrUsageEject [] = "Eject";
const char pstrUsageRandomPlay [] = "Random";
const char pstrUsageSelectDisk [] = "Sel Disk";
const char pstrUsageEnterDisk [] = "Ent Disk";
//const char pstrUsageRepeat [] = "Repeat";
const char pstrUsageTracking [] = "Tracking";
const char pstrUsageTrackNormal [] = "Trk Norm";
const char pstrUsageSlowTracking [] = "Slow Trk";
const char pstrUsageFrameForward [] = "Frm Fwd";
const char pstrUsageFrameBackwards [] = "Frm Back";
const char pstrUsageMark [] = "Mark";
const char pstrUsageClearMark [] = "Clr Mark";
const char pstrUsageRepeatFromMark [] = "Rpt Mark";
const char pstrUsageReturnToMark [] = "Ret to Mark";
const char pstrUsageSearchMarkForward [] = "Search Mark Fwd";
const char pstrUsageSearchMarkBackwards [] = "Search Mark Back";
const char pstrUsageCounterReset [] = "Counter Reset";
const char pstrUsageShowCounter [] = "Show Counter";
const char pstrUsageTrackingIncrement [] = "Track Inc";
const char pstrUsageTrackingDecrement [] = "Track Dec";
const char pstrUsageStopEject [] = "Stop/Eject";
const char pstrUsagePlayPause [] = "Play/Pause";
const char pstrUsagePlaySkip [] = "Play/Skip";
const char pstrUsageVolume [] = "Vol";
const char pstrUsageBalance [] = "Balance";
//const char pstrUsageMute [] = "Mute";
const char pstrUsageBass [] = "Bass";
const char pstrUsageTreble [] = "Treble";
const char pstrUsageBassBoost [] = "Bass Boost";
const char pstrUsageSurroundMode [] = "Surround";
const char pstrUsageLoudness [] = "Loud";
const char pstrUsageMPX [] = "MPX";
const char pstrUsageVolumeIncrement [] = "Vol Inc";
const char pstrUsageVolumeDecrement [] = "Vol Dec";
const char pstrUsageSpeedSelect [] = "Speed";
const char pstrUsagePlaybackSpeed [] = "Play Speed";
const char pstrUsageStandardPlay [] = "Std Play";
const char pstrUsageLongPlay [] = "Long Play";
const char pstrUsageExtendedPlay [] = "Ext Play";
const char pstrUsageSlow [] = "Slow";
const char pstrUsageFanEnable [] = "Fan Enbl";
const char pstrUsageFanSpeed [] = "Fan Speed";
const char pstrUsageLightEnable [] = "Light Enbl";
const char pstrUsageLightIlluminationLevel [] = "Light Illum Lev";
const char pstrUsageClimateControlEnable [] = "Climate Enbl";
const char pstrUsageRoomTemperature [] = "Room Temp";
const char pstrUsageSecurityEnable [] = "Secur Enbl";
const char pstrUsageFireAlarm [] = "Fire Alm";
const char pstrUsagePoliceAlarm [] = "Police Alm";
const char pstrUsageProximity [] = "Prox";
const char pstrUsageMotion [] = "Motion";
const char pstrUsageDuresAlarm [] = "Dures Alm";
const char pstrUsageHoldupAlarm [] = "Holdup Alm";
const char pstrUsageMedicalAlarm [] = "Med Alm";
const char pstrUsageBalanceRight [] = "Balance Right";
const char pstrUsageBalanceLeft [] = "Balance Left";
const char pstrUsageBassIncrement [] = "Bass Inc";
const char pstrUsageBassDecrement [] = "Bass Dec";
const char pstrUsageTrebleIncrement [] = "Treble Inc";
const char pstrUsageTrebleDecrement [] = "Treble Dec";
const char pstrUsageSpeakerSystem [] = "Spk Sys";
const char pstrUsageChannelLeft [] = "Ch Left";
const char pstrUsageChannelRight [] = "Ch Right";
const char pstrUsageChannelCenter [] = "Ch Center";
const char pstrUsageChannelFront [] = "Ch Front";
const char pstrUsageChannelCenterFront [] = "Ch Cntr Front";
const char pstrUsageChannelSide [] = "Ch Side";
const char pstrUsageChannelSurround [] = "Ch Surround";
const char pstrUsageChannelLowFreqEnhancement [] = "Ch Low Freq Enh";
const char pstrUsageChannelTop [] = "Ch Top";
const char pstrUsageChannelUnknown [] = "Ch Unk";
const char pstrUsageSubChannel [] = "Sub-ch";
const char pstrUsageSubChannelIncrement [] = "Sub-ch Inc";
const char pstrUsageSubChannelDecrement [] = "Sub-ch Dec";
const char pstrUsageAlternateAudioIncrement [] = "Alt Aud Inc";
const char pstrUsageAlternateAudioDecrement [] = "Alt Aud Dec";
const char pstrUsageApplicationLaunchButtons [] = "App Launch Btns";
const char pstrUsageALLaunchButtonConfigTool [] = "AL Launch Conf Tl";
const char pstrUsageALProgrammableButton [] = "AL Pgm Btn";
const char pstrUsageALConsumerControlConfig [] = "AL Cons Ctrl Cfg";
const char pstrUsageALWordProcessor [] = "AL Word Proc";
const char pstrUsageALTextEditor [] = "AL Txt Edtr";
const char pstrUsageALSpreadsheet [] = "AL Sprdsheet";
const char pstrUsageALGraphicsEditor [] = "AL Graph Edtr";
const char pstrUsageALPresentationApp [] = "AL Present App";
const char pstrUsageALDatabaseApp [] = "AL DB App";
const char pstrUsageALEmailReader [] = "AL E-mail Rdr";
const char pstrUsageALNewsreader [] = "AL Newsrdr";
const char pstrUsageALVoicemail [] = "AL Voicemail";
const char pstrUsageALContactsAddressBook [] = "AL Addr Book";
const char pstrUsageALCalendarSchedule [] = "AL Clndr/Schdlr";
const char pstrUsageALTaskProjectManager [] = "AL Task/Prj Mgr";
const char pstrUsageALLogJournalTimecard [] = "AL Log/Jrnl/Tmcrd";
const char pstrUsageALCheckbookFinance [] = "AL Chckbook/Fin";
const char pstrUsageALCalculator [] = "AL Calc";
const char pstrUsageALAVCapturePlayback [] = "AL A/V Capt/Play";
const char pstrUsageALLocalMachineBrowser [] = "AL Loc Mach Brow";
const char pstrUsageALLANWANBrow [] = "AL LAN/WAN Brow";
const char pstrUsageALInternetBrowser [] = "AL I-net Brow";
const char pstrUsageALRemoteNetISPConnect [] = "AL Rem Net Con";
const char pstrUsageALNetworkConference [] = "AL Net Conf";
const char pstrUsageALNetworkChat [] = "AL Net Chat";
const char pstrUsageALTelephonyDialer [] = "AL Tel/Dial";
const char pstrUsageALLogon [] = "AL Logon";
const char pstrUsageALLogoff [] = "AL Logoff";
const char pstrUsageALLogonLogoff [] = "AL Logon/Logoff";
const char pstrUsageALTermLockScrSav [] = "AL Term Lock/Scr Sav";
const char pstrUsageALControlPannel [] = "AL Ctrl Pan";
const char pstrUsageALCommandLineProcessorRun [] = "AL Cmd/Run";
const char pstrUsageALProcessTaskManager [] = "AL Task Mgr";
const char pstrUsageALSelectTaskApplication [] = "AL Sel App";
const char pstrUsageALNextTaskApplication [] = "AL Next App";
const char pstrUsageALPreviousTaskApplication [] = "AL Prev App";
const char pstrUsageALPreemptiveHaltTaskApp [] = "AL Prmpt Halt App";
const char pstrUsageALIntegratedHelpCenter [] = "AL Hlp Cntr";
const char pstrUsageALDocuments [] = "AL Docs";
const char pstrUsageALThesaurus [] = "AL Thsrs";
const char pstrUsageALDictionary [] = "AL Dict";
const char pstrUsageALDesktop [] = "AL Desktop";
const char pstrUsageALSpellCheck [] = "AL Spell Chk";
const char pstrUsageALGrammarCheck [] = "AL Gram Chk";
const char pstrUsageALWirelessStatus [] = "AL Wireless Sts";
const char pstrUsageALKeyboardLayout [] = "AL Kbd Layout";
const char pstrUsageALVirusProtection [] = "AL Vir Protect";
const char pstrUsageALEncryption [] = "AL Encrypt";
const char pstrUsageALScreenSaver [] = "AL Scr Sav";
const char pstrUsageALAlarms [] = "AL Alarms";
const char pstrUsageALClock [] = "AL Clock";
const char pstrUsageALFileBrowser [] = "AL File Brow";
const char pstrUsageALPowerStatus [] = "AL Pwr Sts";
const char pstrUsageALImageBrowser [] = "AL Img Brow";
const char pstrUsageALAudioBrowser [] = "AL Aud Brow";
const char pstrUsageALMovieBrowser [] = "AL Mov Brow";
const char pstrUsageALDigitalRightsManager [] = "AL Dig Rights Mgr";
const char pstrUsageALDigitalWallet [] = "AL Dig Wallet";
const char pstrUsageALInstantMessaging [] = "AL Inst Msg";
const char pstrUsageALOEMFeaturesBrowser [] = "AL OEM Tips Brow";
const char pstrUsageALOEMHelp [] = "AL OEM Hlp";
const char pstrUsageALOnlineCommunity [] = "AL Online Com";
const char pstrUsageALEntertainmentContentBrow [] = "AL Ent Cont Brow";
const char pstrUsageALOnlineShoppingBrowser [] = "AL Online Shop Brow";
const char pstrUsageALSmartCardInfoHelp [] = "AL SmartCard Inf";
const char pstrUsageALMarketMonitorFinBrowser [] = "AL Market Brow";
const char pstrUsageALCustomCorpNewsBrowser [] = "AL Cust Corp News Brow";
const char pstrUsageALOnlineActivityBrowser [] = "AL Online Act Brow";
const char pstrUsageALResearchSearchBrowser [] = "AL Search Brow";
const char pstrUsageALAudioPlayer [] = "AL Aud Player";
const char pstrUsageGenericGUIAppControls [] = "Gen GUI App Ctrl";
const char pstrUsageACNew [] = "AC New";
const char pstrUsageACOpen [] = "AC Open";
const char pstrUsageACClose [] = "AC Close";
const char pstrUsageACExit [] = "AC Exit";
const char pstrUsageACMaximize [] = "AC Max";
const char pstrUsageACMinimize [] = "AC Min";
const char pstrUsageACSave [] = "AC Save";
const char pstrUsageACPrint [] = "AC Print";
const char pstrUsageACProperties [] = "AC Prop";
const char pstrUsageACUndo [] = "AC Undo";
const char pstrUsageACCopy [] = "AC Copy";
const char pstrUsageACCut [] = "AC Cut";
const char pstrUsageACPaste [] = "AC Paste";
const char pstrUsageACSelectAll [] = "AC Sel All";
const char pstrUsageACFind [] = "AC Find";
const char pstrUsageACFindAndReplace [] = "AC Find/Replace";
const char pstrUsageACSearch [] = "AC Search";
const char pstrUsageACGoto [] = "AC Goto";
const char pstrUsageACHome [] = "AC Home";
const char pstrUsageACBack [] = "AC Back";
const char pstrUsageACForward [] = "AC Fwd";
const char pstrUsageACStop [] = "AC Stop";
const char pstrUsageACRefresh [] = "AC Refresh";
const char pstrUsageACPreviousLink [] = "AC Prev Link";
const char pstrUsageACNextLink [] = "AC Next Link";
const char pstrUsageACBookmarks [] = "AC Bkmarks";
const char pstrUsageACHistory [] = "AC Hist";
const char pstrUsageACSubscriptions [] = "AC Subscr";
const char pstrUsageACZoomIn [] = "AC Zoom In";
const char pstrUsageACZoomOut [] = "AC Zoom Out";
const char pstrUsageACZoom [] = "AC Zoom";
const char pstrUsageACFullScreenView [] = "AC Full Scr";
const char pstrUsageACNormalView [] = "AC Norm View";
const char pstrUsageACViewToggle [] = "AC View Tgl";
const char pstrUsageACScrollUp [] = "AC Scroll Up";
const char pstrUsageACScrollDown [] = "AC Scroll Down";
const char pstrUsageACScroll [] = "AC Scroll";
const char pstrUsageACPanLeft [] = "AC Pan Left";
const char pstrUsageACPanRight [] = "AC Pan Right";
const char pstrUsageACPan [] = "AC Pan";
const char pstrUsageACNewWindow [] = "AC New Wnd";
const char pstrUsageACTileHoriz [] = "AC Tile Horiz";
const char pstrUsageACTileVert [] = "AC Tile Vert";
const char pstrUsageACFormat [] = "AC Frmt";
const char pstrUsageACEdit [] = "AC Edit";
const char pstrUsageACBold [] = "AC Bold";
const char pstrUsageACItalics [] = "AC Ital";
const char pstrUsageACUnderline [] = "AC Under";
const char pstrUsageACStrikethrough [] = "AC Strike";
const char pstrUsageACSubscript [] = "AC Sub";
const char pstrUsageACSuperscript [] = "AC Super";
const char pstrUsageACAllCaps [] = "AC All Caps";
const char pstrUsageACRotate [] = "AC Rotate";
const char pstrUsageACResize [] = "AC Resize";
const char pstrUsageACFlipHorizontal [] = "AC Flp H";
const char pstrUsageACFlipVertical [] = "AC Flp V";
const char pstrUsageACMirrorHorizontal [] = "AC Mir H";
const char pstrUsageACMirrorVertical [] = "AC Mir V";
const char pstrUsageACFontSelect [] = "AC Fnt Sel";
const char pstrUsageACFontColor [] = "AC Fnt Clr";
const char pstrUsageACFontSize [] = "AC Fnt Size";
const char pstrUsageACJustifyLeft [] = "AC Just Left";
const char pstrUsageACJustifyCenterH [] = "AC Just Cent H";
const char pstrUsageACJustifyRight [] = "AC Just Right";
const char pstrUsageACJustifyBlockH [] = "AC Just Block H";
const char pstrUsageACJustifyTop [] = "AC Just Top";
const char pstrUsageACJustifyCenterV [] = "AC Just Cent V";
const char pstrUsageACJustifyBottom [] = "AC Just Bot";
const char pstrUsageACJustifyBlockV [] = "AC Just Block V";
const char pstrUsageACIndentDecrease [] = "AC Indent Dec";
const char pstrUsageACIndentIncrease [] = "AC Indent Inc";
const char pstrUsageACNumberedList [] = "AC Num List";
const char pstrUsageACRestartNumbering [] = "AC Res Num";
const char pstrUsageACBulletedList [] = "AC Blt List";
const char pstrUsageACPromote [] = "AC Promote";
const char pstrUsageACDemote [] = "AC Demote";
const char pstrUsageACYes [] = "AC Yes";
const char pstrUsageACNo [] = "AC No";
const char pstrUsageACCancel [] = "AC Cancel";
const char pstrUsageACCatalog [] = "AC Ctlg";
const char pstrUsageACBuyChkout [] = "AC Buy";
const char pstrUsageACAddToCart [] = "AC Add2Cart";
const char pstrUsageACExpand [] = "AC Xpnd";
const char pstrUsageACExpandAll [] = "AC Xpand All";
const char pstrUsageACCollapse [] = "AC Collapse";
const char pstrUsageACCollapseAll [] = "AC Collapse All";
const char pstrUsageACPrintPreview [] = "AC Prn Prevw";
const char pstrUsageACPasteSpecial [] = "AC Paste Spec";
const char pstrUsageACInsertMode [] = "AC Ins Mode";
const char pstrUsageACDelete [] = "AC Del";
const char pstrUsageACLock [] = "AC Lock";
const char pstrUsageACUnlock [] = "AC Unlock";
const char pstrUsageACProtect [] = "AC Prot";
const char pstrUsageACUnprotect [] = "AC Unprot";
const char pstrUsageACAttachComment [] = "AC Attach Cmnt";
const char pstrUsageACDeleteComment [] = "AC Del Cmnt";
const char pstrUsageACViewComment [] = "AC View Cmnt";
const char pstrUsageACSelectWord [] = "AC Sel Word";
const char pstrUsageACSelectSentence [] = "AC Sel Sntc";
const char pstrUsageACSelectParagraph [] = "AC Sel Para";
const char pstrUsageACSelectColumn [] = "AC Sel Col";
const char pstrUsageACSelectRow [] = "AC Sel Row";
const char pstrUsageACSelectTable [] = "AC Sel Tbl";
const char pstrUsageACSelectObject [] = "AC Sel Obj";
const char pstrUsageACRedoRepeat [] = "AC Redo";
const char pstrUsageACSort [] = "AC Sort";
const char pstrUsageACSortAscending [] = "AC Sort Asc";
const char pstrUsageACSortDescending [] = "AC Sort Desc";
const char pstrUsageACFilter [] = "AC Filt";
const char pstrUsageACSetClock [] = "AC Set Clk";
const char pstrUsageACViewClock [] = "AC View Clk";
const char pstrUsageACSelectTimeZone [] = "AC Sel Time Z";
const char pstrUsageACEditTimeZone [] = "AC Edt Time Z";
const char pstrUsageACSetAlarm [] = "AC Set Alm";
const char pstrUsageACClearAlarm [] = "AC Clr Alm";
const char pstrUsageACSnoozeAlarm [] = "AC Snz Alm";
const char pstrUsageACResetAlarm [] = "AC Rst Alm";
const char pstrUsageACSyncronize [] = "AC Sync";
const char pstrUsageACSendReceive [] = "AC Snd/Rcv";
const char pstrUsageACSendTo [] = "AC Snd To";
const char pstrUsageACReply [] = "AC Reply";
const char pstrUsageACReplyAll [] = "AC Reply All";
const char pstrUsageACForwardMessage [] = "AC Fwd Msg";
const char pstrUsageACSend [] = "AC Snd";
const char pstrUsageACAttachFile [] = "AC Att File";
const char pstrUsageACUpload [] = "AC Upld";
const char pstrUsageACDownload [] = "AC Dnld";
const char pstrUsageACSetBorders [] = "AC Set Brd";
const char pstrUsageACInsertRow [] = "AC Ins Row";
const char pstrUsageACInsertColumn [] = "AC Ins Col";
const char pstrUsageACInsertFile [] = "AC Ins File";
const char pstrUsageACInsertPicture [] = "AC Ins Pic";
const char pstrUsageACInsertObject [] = "AC Ins Obj";
const char pstrUsageACInsertSymbol [] = "AC Ins Sym";
const char pstrUsageACSaveAndClose [] = "AC Sav&Cls";
const char pstrUsageACRename [] = "AC Rename";
const char pstrUsageACMerge [] = "AC Merge";
const char pstrUsageACSplit [] = "AC Split";
const char pstrUsageACDistributeHorizontaly [] = "AC Dist Hor";
const char pstrUsageACDistributeVerticaly [] = "AC Dist Ver";
// Digitaizers
const char pstrUsageDigitizer [] = "Digitizer";
const char pstrUsagePen [] = "Pen";
const char pstrUsageLightPen [] = "Light Pen";
const char pstrUsageTouchScreen [] = "Touch Scr";
const char pstrUsageTouchPad [] = "Touch Pad";
const char pstrUsageWhiteBoard [] = "White Brd";
const char pstrUsageCoordinateMeasuringMachine [] = "Coord Meas Mach";
const char pstrUsage3DDigitizer [] = "3D Dgtz";
const char pstrUsageStereoPlotter [] = "Stereo Plot";
const char pstrUsageArticulatedArm [] = "Art Arm";
const char pstrUsageArmature [] = "Armature";
const char pstrUsageMultiplePointDigitizer [] = "Multi Point Dgtz";
const char pstrUsageFreeSpaceWand [] = "Free Space Wand";
const char pstrUsageStylus [] = "Stylus";
const char pstrUsagePuck [] = "Puck";
const char pstrUsageFinger [] = "Finger";
const char pstrUsageTipPressure [] = "Tip Press";
const char pstrUsageBarrelPressure [] = "Brl Press";
const char pstrUsageInRange [] = "In Range";
const char pstrUsageTouch [] = "Touch";
const char pstrUsageUntouch [] = "Untouch";
const char pstrUsageTap [] = "Tap";
const char pstrUsageQuality [] = "Qlty";
const char pstrUsageDataValid [] = "Data Valid";
const char pstrUsageTransducerIndex [] = "Transducer Ind";
const char pstrUsageTabletFunctionKeys [] = "Tabl Func Keys";
const char pstrUsageProgramChangeKeys [] = "Pgm Chng Keys";
//const char pstrUsageBatteryStrength [] = "Bat Strength";
const char pstrUsageInvert [] = "Invert";
const char pstrUsageXTilt [] = "X Tilt";
const char pstrUsageYTilt [] = "Y Tilt";
const char pstrUsageAzimuth [] = "Azimuth";
const char pstrUsageAltitude [] = "Altitude";
const char pstrUsageTwist [] = "Twist";
const char pstrUsageTipSwitch [] = "Tip Sw";
const char pstrUsageSecondaryTipSwitch [] = "Scnd Tip Sw";
const char pstrUsageBarrelSwitch [] = "Brl Sw";
const char pstrUsageEraser [] = "Eraser";
const char pstrUsageTabletPick [] = "Tbl Pick";
// Alphanumeric Display Page
const char pstrUsageAlphanumericDisplay [] = "Alphanum Disp";
const char pstrUsageBitmappedDisplay [] = "Bmp Disp";
const char pstrUsageDisplayAttributesReport [] = "Disp Attr Rpt";
const char pstrUsageASCIICharacterSet [] = "ASCII chset";
const char pstrUsageDataReadBack [] = "Data Rd Back";
const char pstrUsageFontReadBack [] = "Fnt Rd Back";
const char pstrUsageDisplayControlReport [] = "Disp Ctrl Rpt";
const char pstrUsageClearDisplay [] = "Clr Disp";
//const char pstrUsageDisplayEnable [] = "Disp Enbl";
const char pstrUsageScreenSaverDelay [] = "Scr Sav Delay";
const char pstrUsageScreenSaverEnable [] = "Scr Sav Enbl";
const char pstrUsageVerticalScroll [] = "V Scroll";
const char pstrUsageHorizontalScroll [] = "H Scroll";
const char pstrUsageCharacterReport [] = "Char Rpt";
const char pstrUsageDisplayData [] = "Disp Data";
const char pstrUsageDisplayStatus [] = "Disp Stat";
const char pstrUsageStatusNotReady [] = "Stat !Ready";
const char pstrUsageStatusReady [] = "Stat Ready";
const char pstrUsageErrorNotALoadableCharacter [] = "Err Not Ld Char";
const char pstrUsageErrorFotDataCanNotBeRead [] = "Fnt Data Rd Err";
const char pstrUsageCursorPositionReport [] = "Cur Pos Rpt";
const char pstrUsageRow [] = "Row";
const char pstrUsageColumn [] = "Col";
const char pstrUsageRows [] = "Rows";
const char pstrUsageColumns [] = "Cols";
const char pstrUsageCursorPixelPosition [] = "Cur Pix Pos";
const char pstrUsageCursorMode [] = "Cur Mode";
const char pstrUsageCursorEnable [] = "Cur Enbl";
const char pstrUsageCursorBlink [] = "Cur Blnk";
const char pstrUsageFontReport [] = "Fnt Rpt";
const char pstrUsageFontData [] = "Fnt Data";
const char pstrUsageCharacterWidth [] = "Char Wdth";
const char pstrUsageCharacterHeight [] = "Char Hght";
const char pstrUsageCharacterSpacingHorizontal [] = "Char Space H";
const char pstrUsageCharacterSpacingVertical [] = "Char Space V";
const char pstrUsageUnicodeCharset [] = "Unicode Char";
const char pstrUsageFont7Segment [] = "Fnt 7-seg";
const char pstrUsage7SegmentDirectMap [] = "7-seg map";
const char pstrUsageFont14Segment [] = "Fnt 14-seg";
const char pstrUsage14SegmentDirectMap [] = "14-seg map";
const char pstrUsageDisplayBrightness [] = "Disp Bright";
const char pstrUsageDisplayContrast [] = "Disp Cntrst";
const char pstrUsageCharacterAttribute [] = "Char Attr";
const char pstrUsageAttributeReadback [] = "Attr Readbk";
const char pstrUsageAttributeData [] = "Attr Data";
const char pstrUsageCharAttributeEnhance [] = "Char Attr Enh";
const char pstrUsageCharAttributeUnderline [] = "Char Attr Undl";
const char pstrUsageCharAttributeBlink [] = "Char Attr Blnk";
const char pstrUsageBitmapSizeX [] = "Bmp Size X";
const char pstrUsageBitmapSizeY [] = "Bmp Size Y";
const char pstrUsageBitDepthFormat [] = "Bit Dpth Fmt";
const char pstrUsageDisplayOrientation [] = "Disp Ornt";
const char pstrUsagePaletteReport [] = "Pal Rpt";
const char pstrUsagePaletteDataSize [] = "Pal Data Size";
const char pstrUsagePaletteDataOffset [] = "Pal Data Off";
const char pstrUsagePaletteData [] = "Pal Data";
const char pstrUsageBlitReport [] = "Blit Rpt";
const char pstrUsageBlitRectangleX1 [] = "Blit Rect X1";
const char pstrUsageBlitRectangleY1 [] = "Blit Rect Y1";
const char pstrUsageBlitRectangleX2 [] = "Blit Rect X2";
const char pstrUsageBlitRectangleY2 [] = "Blit Rect Y2";
const char pstrUsageBlitData [] = "Blit Data";
const char pstrUsageSoftButton [] = "Soft Btn";
const char pstrUsageSoftButtonID [] = "Soft Btn ID";
const char pstrUsageSoftButtonSide [] = "Soft Btn Side";
const char pstrUsageSoftButtonOffset1 [] = "Soft Btn Off1";
const char pstrUsageSoftButtonOffset2 [] = "Soft Btn Off2";
const char pstrUsageSoftButtonReport [] = "Soft Btn Rpt";
// Medical Instrument Page
const char pstrUsageMedicalUltrasound [] = "Med Ultrasnd";
const char pstrUsageVCRAcquisition [] = "VCR/Acq";
const char pstrUsageFreezeThaw [] = "Freeze";
const char pstrUsageClipStore [] = "Clip Store";
const char pstrUsageUpdate [] = "Update";
const char pstrUsageNext [] = "Next";
const char pstrUsageSave [] = "Save";
const char pstrUsagePrint [] = "Print";
const char pstrUsageMicrophoneEnable [] = "Mic Enbl";
const char pstrUsageCine [] = "Cine";
const char pstrUsageTransmitPower [] = "Trans Pwr";
//const char pstrUsageVolume [] = "Vol";
const char pstrUsageFocus [] = "Focus";
const char pstrUsageDepth [] = "Depth";
const char pstrUsageSoftStepPrimary [] = "Soft Stp-Pri";
const char pstrUsageSoftStepSecondary [] = "Soft Stp-Sec";
const char pstrUsageDepthGainCompensation [] = "Dpth Gain Comp";
const char pstrUsageZoomSelect [] = "Zoom Sel";
const char pstrUsageZoomAdjust [] = "Zoom Adj";
const char pstrUsageSpectralDopplerModeSelect [] = "Spec Dop Mode Sel";
const char pstrUsageSpectralDopplerModeAdjust [] = "Spec Dop Mode Adj";
const char pstrUsageColorDopplerModeSelect [] = "Color Dop Mode Sel";
const char pstrUsageColorDopplerModeAdjust [] = "Color Dop Mode Adj";
const char pstrUsageMotionModeSelect [] = "Motion Mode Sel";
const char pstrUsageMotionModeAdjust [] = "Motion Mode Adj";
const char pstrUsage2DModeSelect [] = "2D Mode Sel";
const char pstrUsage2DModeAdjust [] = "2D Mode Adj";
const char pstrUsageSoftControlSelect [] = "Soft Ctrl Sel";
const char pstrUsageSoftControlAdjust [] = "Soft Ctrl Adj";
//extern const char *usagePageTitles0[15];
//const char *usagePageTitles1[];
//const char *genDesktopTitles0[];
//const char *genDesktopTitles1[];
//const char *genDesktopTitles2[];
//const char *genDesktopTitles3[];
//const char *genDesktopTitles4[];
//const char *simuTitles0[];
//const char *simuTitles1[];
//const char *simuTitles2[];
//const char *vrTitles0[];
//const char *vrTitles1[];
//const char *sportsCtrlTitles0[];
//const char *sportsCtrlTitles1[];
//const char *sportsCtrlTitles2[];
//const char *gameTitles0[];
//const char *gameTitles1[];
//const char *genDevCtrlTitles[];
//const char *ledTitles[];
//const char *telTitles0[];
//const char *telTitles1[];
//const char *telTitles2[];
//const char *telTitles3[];
//const char *telTitles4[];
//const char *telTitles5[];
//const char *consTitles0[];
//const char *consTitles1[];
//const char *consTitles2[];
//const char *consTitles3[];
//const char *consTitles4[];
//const char *consTitles5[];
//const char *consTitles6[];
//const char *consTitles7[];
//const char *consTitles8[];
//const char *consTitles9[];
//const char *consTitlesA[];
//const char *consTitlesB[];
//const char *consTitlesC[];
//const char *consTitlesD[];
//const char *consTitlesE[];
//const char *digitTitles0[];
//const char *digitTitles1[];
//const char *digitTitles2[];
//const char *aplphanumTitles0[];
//const char *aplphanumTitles1[];
//const char *aplphanumTitles2[];
//const char *medInstrTitles0[];
//const char *medInstrTitles1[];
//const char *medInstrTitles2[];
//const char *medInstrTitles3[];
//const char *medInstrTitles4[];
#endif /* HIDUSAGESTR_H_INCLUDED */

View File

@@ -1,35 +0,0 @@
#######################################
# Syntax Coloring Map For USBHost
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
MouseController KEYWORD1
USBHost KEYWORD1
KeyboardController KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
Task KEYWORD2
mouseMoved KEYWORD2
mouseDragged KEYWORD2
mousePressed KEYWORD2
mouseReleased KEYWORD2
getXChange KEYWORD2
getYChange KEYWORD2
getButton KEYWORD2
keyPressed KEYWORD2
keyReleased KEYWORD2
getModifiers KEYWORD2
getKey KEYWORD2
getOemKey KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -1,73 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#include "parsetools.h"
bool MultiByteValueParser::Parse(uint8_t **pp, uint32_t *pcntdn)
{
if (!pBuf)
{
//Notify(PSTR("Buffer pointer is NULL!\r\n"));
return false;
}
for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
pBuf[valueSize-countDown] = (**pp);
if (countDown)
return false;
countDown = valueSize;
return true;
}
bool PTPListParser::Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me)
{
switch (nStage)
{
case 0:
pBuf->valueSize = lenSize;
theParser.Initialize(pBuf);
nStage = 1;
case 1:
if (!theParser.Parse(pp, pcntdn))
return false;
arLen = 0;
arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
arLenCntdn = arLen;
nStage = 2;
case 2:
pBuf->valueSize = valSize;
theParser.Initialize(pBuf);
nStage = 3;
case 3:
for (; arLenCntdn; arLenCntdn--)
{
if (!theParser.Parse(pp, pcntdn))
return false;
if (pf)
pf(pBuf, (arLen - arLenCntdn), me);
}
nStage = 0;
}
return true;
}

View File

@@ -1,143 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#ifndef PARSETOOLS_H_INCLUDED
#define PARSETOOLS_H_INCLUDED
#include <stdint.h>
#include "Arduino.h"
struct MultiValueBuffer
{
uint8_t valueSize;
void *pValue;
};
class MultiByteValueParser
{
uint8_t *pBuf;
uint32_t countDown;
uint32_t valueSize;
public:
MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {};
const uint8_t* GetBuffer() { return pBuf; };
void Initialize(MultiValueBuffer * const pbuf)
{
pBuf = (uint8_t*)pbuf->pValue;
countDown = valueSize = pbuf->valueSize;
};
bool Parse(uint8_t **pp, uint32_t *pcntdn);
};
class ByteSkipper
{
uint8_t *pBuf;
uint32_t nStage;
uint32_t countDown;
public:
ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {};
void Initialize(MultiValueBuffer *pbuf)
{
pBuf = (uint8_t*)pbuf->pValue;
countDown = 0;
};
bool Skip(uint8_t **pp, uint32_t *pcntdn, uint32_t bytes_to_skip)
{
switch (nStage)
{
case 0:
countDown = bytes_to_skip;
nStage ++;
case 1:
for (; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
if (!countDown)
nStage = 0;
};
return (!countDown);
};
};
// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser
typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me);
class PTPListParser
{
public:
enum ParseMode { modeArray, modeRange/*, modeEnum*/ };
private:
uint32_t nStage;
uint32_t enStage;
uint32_t arLen;
uint32_t arLenCntdn;
uint32_t lenSize; // size of the array length field in bytes
uint32_t valSize; // size of the array element in bytes
MultiValueBuffer *pBuf;
// The only parser for both size and array element parsing
MultiByteValueParser theParser;
uint32_t /*ParseMode*/ prsMode;
public:
PTPListParser() :
nStage(0),
enStage(0),
arLen(0),
arLenCntdn(0),
lenSize(0),
valSize(0),
pBuf(NULL),
prsMode(modeArray)
{};
void Initialize(const uint32_t len_size, const uint32_t val_size, MultiValueBuffer * const p, const uint32_t mode = modeArray)
{
pBuf = p;
lenSize = len_size;
valSize = val_size;
prsMode = mode;
if (prsMode == modeRange)
{
arLenCntdn = arLen = 3;
nStage = 2;
}
else
{
arLenCntdn = arLen = 0;
nStage = 0;
}
enStage = 0;
theParser.Initialize(p);
};
bool Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL);
};
#endif /* PARSETOOLS_H_INCLUDED */

View File

@@ -1,176 +0,0 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
/* USB chapter 9 structures */
#ifndef USB_CH9_H_INCLUDED
#define USB_CH9_H_INCLUDED
#include <stdint.h>
/* Misc.USB constants */
#define DEV_DESCR_LEN 18 //device descriptor length
#define CONF_DESCR_LEN 9 //configuration descriptor length
#define INTR_DESCR_LEN 9 //interface descriptor length
#define EP_DESCR_LEN 7 //endpoint descriptor length
/* Standard Device Requests */
#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS
#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE
#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE
#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS
#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR
#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR
#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION
#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION
#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE
#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE
#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME
#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up
#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode
/* Setup Data Constants */
#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer
#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer
#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard
#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class
#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor
#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device
#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface
#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint
#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other
/* USB descriptors */
#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor.
#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor.
#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor.
#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor.
#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor.
#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier.
#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration.
#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power.
#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor.
#define HID_DESCRIPTOR_HID 0x21
/* OTG SET FEATURE Constants */
#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP
#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP
#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP
/* USB Endpoint Transfer Types */
#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint.
#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint.
#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint.
#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint.
#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes
/* Standard Feature Selectors for CLEAR_FEATURE Requests */
#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient
#define USB_FEATURE_TEST_MODE 2 // Device recipient
_Pragma("pack(1)")
/* descriptor data structures */
/* Device descriptor structure */
typedef struct
{
uint8_t bLength; // Length of this descriptor.
uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
uint16_t bcdUSB; // USB Spec Release Number (BCD).
uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF).
uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0.
uint16_t idVendor; // Vendor ID (assigned by the USB-IF).
uint16_t idProduct; // Product ID (assigned by the manufacturer).
uint16_t bcdDevice; // Device release number (BCD).
uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer.
uint8_t iProduct; // Index of String Descriptor describing the product.
uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
uint8_t bNumConfigurations; // Number of possible configurations.
} USB_DEVICE_DESCRIPTOR;
/* Configuration descriptor structure */
typedef struct
{
uint8_t bLength; // Length of this descriptor.
uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
uint16_t wTotalLength; // Total length of all descriptors for this configuration.
uint8_t bNumInterfaces; // Number of interfaces in this configuration.
uint8_t bConfigurationValue; // Value of this configuration (1 based).
uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
uint8_t bmAttributes; // Configuration characteristics.
uint8_t bMaxPower; // Maximum power consumed by this configuration.
} USB_CONFIGURATION_DESCRIPTOR;
/* Interface descriptor structure */
typedef struct
{
uint8_t bLength; // Length of this descriptor.
uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
uint8_t bInterfaceNumber; // Number of this interface (0 based).
uint8_t bAlternateSetting; // Value of this alternate interface setting.
uint8_t bNumEndpoints; // Number of endpoints in this interface.
uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
uint8_t iInterface; // Index of String Descriptor describing the interface.
} USB_INTERFACE_DESCRIPTOR;
/* Endpoint descriptor structure */
typedef struct
{
uint8_t bLength; // Length of this descriptor.
uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
uint8_t bmAttributes; // Endpoint transfer type.
uint16_t wMaxPacketSize; // Maximum packet size.
uint8_t bInterval; // Polling interval in frames.
} USB_ENDPOINT_DESCRIPTOR;
/* HID descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID; // HID class specification release
uint8_t bCountryCode;
uint8_t bNumDescriptors; // Number of additional class specific descriptors
uint8_t bDescrType; // Type of class descriptor
uint16_t wDescriptorLength; // Total size of the Report descriptor
} USB_HID_DESCRIPTOR;
typedef struct
{
uint8_t bDescrType; // Type of class descriptor
uint16_t wDescriptorLength; // Total size of the Report descriptor
} HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;
_Pragma("pack()")
#endif /* USB_CH9_H_INCLUDED */

View File

@@ -1,199 +0,0 @@
#include "wifi_drv.h"
#include "WiFi.h"
extern "C" {
#include "utility/wl_definitions.h"
#include "utility/wl_types.h"
#include "debug.h"
}
// XXX: don't make assumptions about the value of MAX_SOCK_NUM.
int16_t WiFiClass::_state[MAX_SOCK_NUM] = { 0, 0, 0, 0 };
uint16_t WiFiClass::_server_port[MAX_SOCK_NUM] = { 0, 0, 0, 0 };
WiFiClass::WiFiClass()
{
// Driver initialization
init();
}
void WiFiClass::init()
{
WiFiDrv::wifiDriverInit();
}
uint8_t WiFiClass::getSocket()
{
for (uint8_t i = 0; i < MAX_SOCK_NUM; ++i)
{
if (WiFiClass::_server_port[i] == 0)
{
return i;
}
}
return NO_SOCKET_AVAIL;
}
char* WiFiClass::firmwareVersion()
{
return WiFiDrv::getFwVersion();
}
int WiFiClass::begin(char* ssid)
{
uint8_t status = WL_IDLE_STATUS;
uint8_t attempts = WL_MAX_ATTEMPT_CONNECTION;
if (WiFiDrv::wifiSetNetwork(ssid, strlen(ssid)) != WL_FAILURE)
{
do
{
delay(WL_DELAY_START_CONNECTION);
status = WiFiDrv::getConnectionStatus();
}
while ((( status == WL_IDLE_STATUS)||(status == WL_SCAN_COMPLETED))&&(--attempts>0));
}else
{
status = WL_CONNECT_FAILED;
}
return status;
}
int WiFiClass::begin(char* ssid, uint8_t key_idx, const char *key)
{
uint8_t status = WL_IDLE_STATUS;
uint8_t attempts = WL_MAX_ATTEMPT_CONNECTION;
// set encryption key
if (WiFiDrv::wifiSetKey(ssid, strlen(ssid), key_idx, key, strlen(key)) != WL_FAILURE)
{
do
{
delay(WL_DELAY_START_CONNECTION);
status = WiFiDrv::getConnectionStatus();
}
while ((( status == WL_IDLE_STATUS)||(status == WL_SCAN_COMPLETED))&&(--attempts>0));
}else{
status = WL_CONNECT_FAILED;
}
return status;
}
int WiFiClass::begin(char* ssid, const char *passphrase)
{
uint8_t status = WL_IDLE_STATUS;
uint8_t attempts = WL_MAX_ATTEMPT_CONNECTION;
// set passphrase
if (WiFiDrv::wifiSetPassphrase(ssid, strlen(ssid), passphrase, strlen(passphrase))!= WL_FAILURE)
{
do
{
delay(WL_DELAY_START_CONNECTION);
status = WiFiDrv::getConnectionStatus();
}
while ((( status == WL_IDLE_STATUS)||(status == WL_SCAN_COMPLETED))&&(--attempts>0));
}else{
status = WL_CONNECT_FAILED;
}
return status;
}
int WiFiClass::disconnect()
{
return WiFiDrv::disconnect();
}
uint8_t* WiFiClass::macAddress(uint8_t* mac)
{
uint8_t* _mac = WiFiDrv::getMacAddress();
memcpy(mac, _mac, WL_MAC_ADDR_LENGTH);
return mac;
}
IPAddress WiFiClass::localIP()
{
IPAddress ret;
WiFiDrv::getIpAddress(ret);
return ret;
}
IPAddress WiFiClass::subnetMask()
{
IPAddress ret;
WiFiDrv::getSubnetMask(ret);
return ret;
}
IPAddress WiFiClass::gatewayIP()
{
IPAddress ret;
WiFiDrv::getGatewayIP(ret);
return ret;
}
char* WiFiClass::SSID()
{
return WiFiDrv::getCurrentSSID();
}
uint8_t* WiFiClass::BSSID(uint8_t* bssid)
{
uint8_t* _bssid = WiFiDrv::getCurrentBSSID();
memcpy(bssid, _bssid, WL_MAC_ADDR_LENGTH);
return bssid;
}
int32_t WiFiClass::RSSI()
{
return WiFiDrv::getCurrentRSSI();
}
uint8_t WiFiClass::encryptionType()
{
return WiFiDrv::getCurrentEncryptionType();
}
int8_t WiFiClass::scanNetworks()
{
uint8_t attempts = 10;
uint8_t numOfNetworks = 0;
if (WiFiDrv::startScanNetworks() == WL_FAILURE)
return WL_FAILURE;
do
{
delay(2000);
numOfNetworks = WiFiDrv::getScanNetworks();
}
while (( numOfNetworks == 0)&&(--attempts>0));
return numOfNetworks;
}
char* WiFiClass::SSID(uint8_t networkItem)
{
return WiFiDrv::getSSIDNetoworks(networkItem);
}
int32_t WiFiClass::RSSI(uint8_t networkItem)
{
return WiFiDrv::getRSSINetoworks(networkItem);
}
uint8_t WiFiClass::encryptionType(uint8_t networkItem)
{
return WiFiDrv::getEncTypeNetowrks(networkItem);
}
uint8_t WiFiClass::status()
{
return WiFiDrv::getConnectionStatus();
}
int WiFiClass::hostByName(const char* aHostname, IPAddress& aResult)
{
return WiFiDrv::getHostByName(aHostname, aResult);
}
WiFiClass WiFi;

View File

@@ -1,183 +0,0 @@
#ifndef WiFi_h
#define WiFi_h
#include <inttypes.h>
extern "C" {
#include "utility/wl_definitions.h"
#include "utility/wl_types.h"
}
#include "IPAddress.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
class WiFiClass
{
private:
static void init();
public:
static int16_t _state[MAX_SOCK_NUM];
static uint16_t _server_port[MAX_SOCK_NUM];
WiFiClass();
/*
* Get the first socket available
*/
static uint8_t getSocket();
/*
* Get firmware version
*/
static char* firmwareVersion();
/* Start Wifi connection for OPEN networks
*
* param ssid: Pointer to the SSID string.
*/
int begin(char* ssid);
/* Start Wifi connection with WEP encryption.
* Configure a key into the device. The key type (WEP-40, WEP-104)
* is determined by the size of the key (5 bytes for WEP-40, 13 bytes for WEP-104).
*
* param ssid: Pointer to the SSID string.
* param key_idx: The key index to set. Valid values are 0-3.
* param key: Key input buffer.
*/
int begin(char* ssid, uint8_t key_idx, const char* key);
/* Start Wifi connection with passphrase
* the most secure supported mode will be automatically selected
*
* param ssid: Pointer to the SSID string.
* param passphrase: Passphrase. Valid characters in a passphrase
* must be between ASCII 32-126 (decimal).
*/
int begin(char* ssid, const char *passphrase);
/*
* Disconnect from the network
*
* return: one value of wl_status_t enum
*/
int disconnect(void);
/*
* Get the interface MAC address.
*
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
*/
uint8_t* macAddress(uint8_t* mac);
/*
* Get the interface IP address.
*
* return: Ip address value
*/
IPAddress localIP();
/*
* Get the interface subnet mask address.
*
* return: subnet mask address value
*/
IPAddress subnetMask();
/*
* Get the gateway ip address.
*
* return: gateway ip address value
*/
IPAddress gatewayIP();
/*
* Return the current SSID associated with the network
*
* return: ssid string
*/
char* SSID();
/*
* Return the current BSSID associated with the network.
* It is the MAC address of the Access Point
*
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
*/
uint8_t* BSSID(uint8_t* bssid);
/*
* Return the current RSSI /Received Signal Strength in dBm)
* associated with the network
*
* return: signed value
*/
int32_t RSSI();
/*
* Return the Encryption Type associated with the network
*
* return: one value of wl_enc_type enum
*/
uint8_t encryptionType();
/*
* Start scan WiFi networks available
*
* return: Number of discovered networks
*/
int8_t scanNetworks();
/*
* Return the SSID discovered during the network scan.
*
* param networkItem: specify from which network item want to get the information
*
* return: ssid string of the specified item on the networks scanned list
*/
char* SSID(uint8_t networkItem);
/*
* Return the encryption type of the networks discovered during the scanNetworks
*
* param networkItem: specify from which network item want to get the information
*
* return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list
*/
uint8_t encryptionType(uint8_t networkItem);
/*
* Return the RSSI of the networks discovered during the scanNetworks
*
* param networkItem: specify from which network item want to get the information
*
* return: signed value of RSSI of the specified item on the networks scanned list
*/
int32_t RSSI(uint8_t networkItem);
/*
* Return Connection status.
*
* return: one of the value defined in wl_status_t
*/
uint8_t status();
/*
* Resolve the given hostname to an IP address.
* param aHostname: Name to be resolved
* param aResult: IPAddress structure to store the returned IP address
* result: 1 if aIPAddrString was successfully converted to an IP address,
* else error code
*/
int hostByName(const char* aHostname, IPAddress& aResult);
friend class WiFiClient;
friend class WiFiServer;
};
extern WiFiClass WiFi;
#endif

View File

@@ -1,180 +0,0 @@
extern "C" {
#include "utility/wl_definitions.h"
#include "utility/wl_types.h"
#include "socket.h"
#include "string.h"
#include "utility/debug.h"
}
#include "WiFi.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "server_drv.h"
uint16_t WiFiClient::_srcport = 1024;
WiFiClient::WiFiClient() : _sock(MAX_SOCK_NUM) {
}
WiFiClient::WiFiClient(uint8_t sock) : _sock(sock) {
}
int WiFiClient::connect(const char* host, uint16_t port) {
IPAddress remote_addr;
if (WiFi.hostByName(host, remote_addr))
{
return connect(remote_addr, port);
}
return 0;
}
int WiFiClient::connect(IPAddress ip, uint16_t port) {
_sock = getFirstSocket();
if (_sock != NO_SOCKET_AVAIL)
{
ServerDrv::startClient(uint32_t(ip), port, _sock);
WiFiClass::_state[_sock] = _sock;
unsigned long start = millis();
// wait 4 second for the connection to close
while (!connected() && millis() - start < 10000)
delay(1);
if (!connected())
{
return 0;
}
}else{
Serial.println("No Socket available");
return 0;
}
return 1;
}
size_t WiFiClient::write(uint8_t b) {
return write(&b, static_cast<size_t>(1));
}
size_t WiFiClient::write(const uint8_t *buf, size_t size) {
if (_sock >= MAX_SOCK_NUM)
{
setWriteError();
return 0;
}
if (size==0)
{
setWriteError();
return 0;
}
if (!ServerDrv::sendData(_sock, buf, size))
{
setWriteError();
return 0;
}
if (!ServerDrv::checkDataSent(_sock))
{
setWriteError();
return 0;
}
return size;
}
int WiFiClient::available() {
if (_sock != 255)
{
return ServerDrv::availData(_sock);
}
return 0;
}
int WiFiClient::read() {
uint8_t b;
if (!available())
return -1;
ServerDrv::getData(_sock, &b);
return b;
}
int WiFiClient::read(uint8_t* buf, size_t size) {
uint16_t _size = size;
if (!ServerDrv::getDataBuf(_sock, buf, &_size))
return -1;
return 0;
}
int WiFiClient::peek() {
uint8_t b;
if (!available())
return -1;
ServerDrv::getData(_sock, &b, 1);
return b;
}
void WiFiClient::flush() {
while (available())
read();
}
void WiFiClient::stop() {
if (_sock == 255)
return;
ServerDrv::stopClient(_sock);
unsigned long start = millis();
// wait a second for the connection to close
while (status() != CLOSED && millis() - start < 1000)
delay(1);
_sock = 255;
}
uint8_t WiFiClient::connected() {
if (_sock == 255) {
return 0;
} else {
uint8_t s = status();
return !(s == LISTEN || s == CLOSED || s == FIN_WAIT_1 ||
s == FIN_WAIT_2 || s == TIME_WAIT ||
s == SYN_SENT || s== SYN_RCVD ||
(s == CLOSE_WAIT && !available()));
}
}
uint8_t WiFiClient::status() {
if (_sock == 255) {
return CLOSED;
} else {
return ServerDrv::getClientState(_sock);
}
}
WiFiClient::operator bool() {
return _sock != 255;
}
// Private Methods
uint8_t WiFiClient::getFirstSocket()
{
for (int i = 0; i < MAX_SOCK_NUM; i++) {
if (WiFiClass::_state[i] == 0)
{
return i;
}
}
return SOCK_NOT_AVAIL;
}

View File

@@ -1,40 +0,0 @@
#ifndef wificlient_h
#define wificlient_h
#include "Arduino.h"
#include "Print.h"
#include "Client.h"
#include "IPAddress.h"
class WiFiClient : public Client {
public:
WiFiClient();
WiFiClient(uint8_t sock);
uint8_t status();
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(const char *host, uint16_t port);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
virtual int available();
virtual int read();
virtual int read(uint8_t *buf, size_t size);
virtual int peek();
virtual void flush();
virtual void stop();
virtual uint8_t connected();
virtual operator bool();
friend class WiFiServer;
using Print::write;
private:
static uint16_t _srcport;
uint8_t _sock; //not used
uint16_t _socket;
uint8_t getFirstSocket();
};
#endif

View File

@@ -1,88 +0,0 @@
#include <string.h>
#include "server_drv.h"
extern "C" {
#include "utility/debug.h"
}
#include "WiFi.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
WiFiServer::WiFiServer(uint16_t port)
{
_port = port;
}
void WiFiServer::begin()
{
uint8_t _sock = WiFiClass::getSocket();
if (_sock != NO_SOCKET_AVAIL)
{
ServerDrv::startServer(_port, _sock);
WiFiClass::_server_port[_sock] = _port;
}
}
WiFiClient WiFiServer::available(byte* status)
{
static int cycle_server_down = 0;
const int TH_SERVER_DOWN = 50;
for (int sock = 0; sock < MAX_SOCK_NUM; sock++)
{
if (WiFiClass::_server_port[sock] == _port)
{
WiFiClient client(sock);
uint8_t _status = client.status();
uint8_t _ser_status = this->status();
if (status != NULL)
*status = _status;
//server not in listen state, restart it
if ((_ser_status == 0)&&(cycle_server_down++ > TH_SERVER_DOWN))
{
ServerDrv::startServer(_port, sock);
cycle_server_down = 0;
}
if (_status == ESTABLISHED)
{
return client; //TODO
}
}
}
return WiFiClient(255);
}
uint8_t WiFiServer::status() {
return ServerDrv::getServerState(0);
}
size_t WiFiServer::write(uint8_t b)
{
return write(&b, 1);
}
size_t WiFiServer::write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
for (int sock = 0; sock < MAX_SOCK_NUM; sock++)
{
if (WiFiClass::_server_port[sock] != 0)
{
WiFiClient client(sock);
if (WiFiClass::_server_port[sock] == _port &&
client.status() == ESTABLISHED)
{
n+=client.write(buffer, size);
}
}
}
return n;
}

View File

@@ -1,27 +0,0 @@
#ifndef wifiserver_h
#define wifiserver_h
extern "C" {
#include "utility/wl_definitions.h"
}
#include "Server.h"
class WiFiClient;
class WiFiServer : public Server {
private:
uint16_t _port;
void* pcb;
public:
WiFiServer(uint16_t);
WiFiClient available(uint8_t* status = NULL);
void begin();
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
uint8_t status();
using Print::write;
};
#endif

View File

@@ -1,123 +0,0 @@
/*
This example connects to an unencrypted Wifi network.
Then it prints the MAC address of the Wifi shield,
the IP address obtained, and other network details.
Circuit:
* WiFi shield attached
created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
*/
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "yourNetwork"; // the name of your network
int status = WL_IDLE_STATUS; // the Wifi radio's status
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to open SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network");
printCurrentNet();
printWifiData();
}
void loop() {
// check the network connection once every 10 seconds:
delay(10000);
printCurrentNet();
}
void printWifiData() {
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
Serial.print(mac[5],HEX);
Serial.print(":");
Serial.print(mac[4],HEX);
Serial.print(":");
Serial.print(mac[3],HEX);
Serial.print(":");
Serial.print(mac[2],HEX);
Serial.print(":");
Serial.print(mac[1],HEX);
Serial.print(":");
Serial.println(mac[0],HEX);
// print your subnet mask:
IPAddress subnet = WiFi.subnetMask();
Serial.print("NetMask: ");
Serial.println(subnet);
// print your gateway address:
IPAddress gateway = WiFi.gatewayIP();
Serial.print("Gateway: ");
Serial.println(gateway);
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
Serial.print(bssid[5],HEX);
Serial.print(":");
Serial.print(bssid[4],HEX);
Serial.print(":");
Serial.print(bssid[3],HEX);
Serial.print(":");
Serial.print(bssid[2],HEX);
Serial.print(":");
Serial.print(bssid[1],HEX);
Serial.print(":");
Serial.println(bssid[0],HEX);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption,HEX);
}

View File

@@ -1,128 +0,0 @@
/*
This example connects to a WEP-encrypted Wifi network.
Then it prints the MAC address of the Wifi shield,
the IP address obtained, and other network details.
If you use 40-bit WEP, you need a key that is 10 characters long,
and the characters must be hexadecimal (0-9 or A-F).
e.g. for 40-bit, ABBADEAF01 will work, but ABBADEAF won't work
(too short) and ABBAISDEAF won't work (I and S are not
hexadecimal characters).
For 128-bit, you need a string that is 26 characters long.
D0D0DEADF00DABBADEAFBEADED will work because it's 26 characters,
all in the 0-9, A-F range.
Circuit:
* WiFi shield attached
created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
*/
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "yourNetwork"; // your network SSID (name)
char key[] = "D0D0DEADF00DABBADEAFBEADED"; // your network key
int keyIndex = 0; // your network key Index number
int status = WL_IDLE_STATUS; // the Wifi radio's status
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WEP network, SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, keyIndex, key);
// wait 10 seconds for connection:
delay(10000);
}
// once you are connected :
Serial.print("You're connected to the network");
printCurrentNet();
printWifiData();
}
void loop() {
// check the network connection once every 10 seconds:
delay(10000);
printCurrentNet();
}
void printWifiData() {
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
Serial.print(mac[5],HEX);
Serial.print(":");
Serial.print(mac[4],HEX);
Serial.print(":");
Serial.print(mac[3],HEX);
Serial.print(":");
Serial.print(mac[2],HEX);
Serial.print(":");
Serial.print(mac[1],HEX);
Serial.print(":");
Serial.println(mac[0],HEX);
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
Serial.print(bssid[5],HEX);
Serial.print(":");
Serial.print(bssid[4],HEX);
Serial.print(":");
Serial.print(bssid[3],HEX);
Serial.print(":");
Serial.print(bssid[2],HEX);
Serial.print(":");
Serial.print(bssid[1],HEX);
Serial.print(":");
Serial.println(bssid[0],HEX);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption,HEX);
Serial.println();
}

View File

@@ -1,118 +0,0 @@
/*
This example connects to an unencrypted Wifi network.
Then it prints the MAC address of the Wifi shield,
the IP address obtained, and other network details.
Circuit:
* WiFi shield attached
created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
*/
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "secretPassword"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network");
printCurrentNet();
printWifiData();
}
void loop() {
// check the network connection once every 10 seconds:
delay(10000);
printCurrentNet();
}
void printWifiData() {
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
Serial.print(mac[5],HEX);
Serial.print(":");
Serial.print(mac[4],HEX);
Serial.print(":");
Serial.print(mac[3],HEX);
Serial.print(":");
Serial.print(mac[2],HEX);
Serial.print(":");
Serial.print(mac[1],HEX);
Serial.print(":");
Serial.println(mac[0],HEX);
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
Serial.print(bssid[5],HEX);
Serial.print(":");
Serial.print(bssid[4],HEX);
Serial.print(":");
Serial.print(bssid[3],HEX);
Serial.print(":");
Serial.print(bssid[2],HEX);
Serial.print(":");
Serial.print(bssid[1],HEX);
Serial.print(":");
Serial.println(bssid[0],HEX);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption,HEX);
Serial.println();
}

View File

@@ -1,118 +0,0 @@
/*
This example prints the Wifi shield's MAC address, and
scans for available Wifi networks using the Wifi shield.
Every ten seconds, it scans again. It doesn't actually
connect to any network, so no encryption scheme is specified.
Circuit:
* WiFi shield attached
created 13 July 2010
by dlf (Metodo2 srl)
modified 21 Junn 2012
by Tom Igoe and Jaymes Dec
*/
#include <SPI.h>
#include <WiFi.h>
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// Print WiFi MAC address:
printMacAddress();
// scan for existing networks:
Serial.println("Scanning available networks...");
listNetworks();
}
void loop() {
delay(10000);
// scan for existing networks:
Serial.println("Scanning available networks...");
listNetworks();
}
void printMacAddress() {
// the MAC address of your Wifi shield
byte mac[6];
// print your MAC address:
WiFi.macAddress(mac);
Serial.print("MAC: ");
Serial.print(mac[5],HEX);
Serial.print(":");
Serial.print(mac[4],HEX);
Serial.print(":");
Serial.print(mac[3],HEX);
Serial.print(":");
Serial.print(mac[2],HEX);
Serial.print(":");
Serial.print(mac[1],HEX);
Serial.print(":");
Serial.println(mac[0],HEX);
}
void listNetworks() {
// scan for nearby networks:
Serial.println("** Scan Networks **");
int numSsid = WiFi.scanNetworks();
if (numSsid == -1)
{
Serial.println("Couldn't get a wifi connection");
while(true);
}
// print the list of networks seen:
Serial.print("number of available networks:");
Serial.println(numSsid);
// print the network number and name for each network found:
for (int thisNet = 0; thisNet<numSsid; thisNet++) {
Serial.print(thisNet);
Serial.print(") ");
Serial.print(WiFi.SSID(thisNet));
Serial.print("\tSignal: ");
Serial.print(WiFi.RSSI(thisNet));
Serial.print(" dBm");
Serial.print("\tEncryption: ");
printEncryptionType(WiFi.encryptionType(thisNet));
}
}
void printEncryptionType(int thisType) {
// read the encryption type and print out the name:
switch (thisType) {
case ENC_TYPE_WEP:
Serial.println("WEP");
break;
case ENC_TYPE_TKIP:
Serial.println("WPA");
break;
case ENC_TYPE_CCMP:
Serial.println("WPA2");
break;
case ENC_TYPE_NONE:
Serial.println("None");
break;
case ENC_TYPE_AUTO:
Serial.println("Auto");
break;
}
}

View File

@@ -1,130 +0,0 @@
/*
WiFi Web Server LED Blink
A simple web server that lets you blink an LED via the web.
This sketch will print the IP address of your WiFi Shield (once connected)
to the Serial monitor. From there, you can open that address in a web browser
to turn on and off the LED on pin 9.
If the IP address of your shield is yourAddress:
http://yourAddress/H turns the LED on
http://yourAddress/L turns it off
This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.
Circuit:
* WiFi shield attached
* LED attached to pin 9
created 25 Nov 2012
by Tom Igoe
*/
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "secretPassword"; // your network password
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiServer server(80);
void setup() {
Serial.begin(9600); // initialize serial communication
pinMode(9, OUTPUT); // set the LED pin mode
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
while(true); // don't continue
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to Network named: ");
Serial.println(ssid); // print the network name (SSID);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
server.begin(); // start the web server on port 80
printWifiStatus(); // you're connected now, so print out the status
}
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Click <a href=\"/H\">here</a> turn the LED on pin 9 on<br>");
client.print("Click <a href=\"/L\">here</a> turn the LED on pin 9 off<br>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
}
else { // if you got a newline, then clear currentLine:
currentLine = "";
}
}
else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(9, HIGH); // GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(9, LOW); // GET /L turns the LED off
}
}
}
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
// print where to go in a browser:
Serial.print("To see this page in action, open a browser to http://");
Serial.println(ip);
}

View File

@@ -1,111 +0,0 @@
/*
Chat Server
A simple server that distributes any incoming messages to all
connected clients. To use telnet to your device's IP address and type.
You can see the client's input in the serial monitor as well.
This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.
Circuit:
* WiFi shield attached
created 18 Dec 2009
by David A. Mellis
modified 31 May 2012
by Tom Igoe
*/
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "secretPassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiServer server(23);
boolean alreadyConnected = false; // whether or not the client was connected previously
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// start the server:
server.begin();
// you're connected now, so print out the status:
printWifiStatus();
}
void loop() {
// wait for a new client:
WiFiClient client = server.available();
// when the client sends the first byte, say hello:
if (client) {
if (!alreadyConnected) {
// clead out the input buffer:
client.flush();
Serial.println("We have a new client");
client.println("Hello, client!");
alreadyConnected = true;
}
if (client.available() > 0) {
// read the bytes incoming from the client:
char thisChar = client.read();
// echo the bytes back to the client:
server.write(thisChar);
// echo the bytes to the server as well:
Serial.write(thisChar);
}
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

View File

@@ -1,191 +0,0 @@
/*
Wifi Pachube sensor client
This sketch connects an analog sensor to Pachube (http://www.pachube.com)
using an Arduino Wifi shield.
This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.
This example has been updated to use version 2.0 of the Pachube API.
To make it work, create a feed with a datastream, and give it the ID
sensor1. Or change the code below to match your feed.
Circuit:
* Analog sensor attached to analog in 0
* Wifi shield attached to pins 10, 11, 12, 13
created 13 Mar 2012
modified 31 May 2012
by Tom Igoe
modified 8 Sept 2012
by Scott Fitzgerald
This code is in the public domain.
*/
#include <SPI.h>
#include <WiFi.h>
#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here
#define FEEDID 00000 // replace your feed ID
#define USERAGENT "My Arduino Project" // user agent is the project name
char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "secretPassword"; // your network password
int status = WL_IDLE_STATUS;
// initialize the library instance:
WiFiClient client;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
IPAddress server(216,52,233,121); // numeric IP for api.pachube.com
//char server[] = "api.pachube.com"; // name address for pachube API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between updates to pachube.com
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the status:
printWifiStatus();
}
void loop() {
// read the analog sensor:
int sensorReading = analogRead(A0);
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
while (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
sendData(sensorReading);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
// this method makes a HTTP connection to the server:
void sendData(int thisData) {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.pachube.com");
client.print("X-ApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
// calculate the length of the sensor reading in bytes:
// 8 bytes for "sensor1," + number of digits of the data:
int thisLength = 8 + getLength(thisData);
client.println(thisLength);
// last pieces of the HTTP PUT request:
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
// here's the actual content of the PUT request:
client.print("sensor1,");
client.println(thisData);
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}
// This method calculates the number of digits in the
// sensor reading. Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:
int getLength(int someValue) {
// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0) {
dividend = dividend /10;
digits++;
}
// return the number of digits:
return digits;
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

View File

@@ -1,177 +0,0 @@
/*
Wifi Pachube sensor client with Strings
This sketch connects an analog sensor to Pachube (http://www.pachube.com)
using a Arduino Wifi shield.
This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.
This example has been updated to use version 2.0 of the pachube.com API.
To make it work, create a feed with a datastream, and give it the ID
sensor1. Or change the code below to match your feed.
This example uses the String library, which is part of the Arduino core from
version 0019.
Circuit:
* Analog sensor attached to analog in 0
* Wifi shield attached to pins 10, 11, 12, 13
created 16 Mar 2012
modified 31 May 2012
by Tom Igoe
modified 8 Sept 2012
by Scott Fitzgerald
This code is in the public domain.
*/
#include <SPI.h>
#include <WiFi.h>
#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here
#define FEEDID 00000 // replace your feed ID
#define USERAGENT "My Arduino Project" // user agent is the project name
char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "secretPassword"; // your network password
int status = WL_IDLE_STATUS;
// initialize the library instance:
WiFiClient client;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(216,52,233,121); // numeric IP for api.pachube.com
char server[] = "api.pachube.com"; // name address for pachube API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between updates to pachube.com
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the status:
printWifiStatus();
}
void loop() {
// read the analog sensor:
int sensorReading = analogRead(A0);
// convert the data to a String to send it:
String dataString = "sensor1,";
dataString += sensorReading;
// you can append multiple readings to this String if your
// pachube feed is set up to handle multiple values:
int otherSensorReading = analogRead(A1);
dataString += "\nsensor2,";
dataString += otherSensorReading;
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
while (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
sendData(dataString);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
// this method makes a HTTP connection to the server:
void sendData(String thisData) {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.pachube.com");
client.print("X-ApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
client.println(thisData.length());
// last pieces of the HTTP PUT request:
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
// here's the actual content of the PUT request:
client.println(thisData);
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

View File

@@ -1,164 +0,0 @@
/*
Wifi Twitter Client with Strings
This sketch connects to Twitter using using an Arduino WiFi shield.
It parses the XML returned, and looks for <text>this is a tweet</text>
This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.
This example uses the String library, which is part of the Arduino core from
version 0019.
Circuit:
* WiFi shield attached to pins 10, 11, 12, 13
created 23 apr 2012
modified 31 May 2012
by Tom Igoe
This code is in the public domain.
*/
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "password"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS; // status of the wifi connection
// initialize the library instance:
WiFiClient client;
const unsigned long requestInterval = 30*1000; // delay between requests; 30 seconds
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(199,59,149,200); // numeric IP for api.twitter.com
char server[] = "api.twitter.com"; // name address for twitter API
boolean requested; // whether you've made a request since connecting
unsigned long lastAttemptTime = 0; // last time you connected to the server, in milliseconds
String currentLine = ""; // string to hold the text from server
String tweet = ""; // string to hold the tweet
boolean readingTweet = false; // if you're currently reading the tweet
void setup() {
// reserve space for the strings:
currentLine.reserve(256);
tweet.reserve(150);
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the status:
printWifiStatus();
connectToServer();
}
void loop()
{
if (client.connected()) {
if (client.available()) {
// read incoming bytes:
char inChar = client.read();
// add incoming byte to end of line:
currentLine += inChar;
// if you get a newline, clear the line:
if (inChar == '\n') {
currentLine = "";
}
// if the current line ends with <text>, it will
// be followed by the tweet:
if ( currentLine.endsWith("<text>")) {
// tweet is beginning. Clear the tweet string:
readingTweet = true;
tweet = "";
// break out of the loop so this character isn't added to the tweet:
return;
}
// if you're currently reading the bytes of a tweet,
// add them to the tweet String:
if (readingTweet) {
if (inChar != '<') {
tweet += inChar;
}
else {
// if you got a "<" character,
// you've reached the end of the tweet:
readingTweet = false;
Serial.println(tweet);
// close the connection to the server:
client.stop();
}
}
}
}
else if (millis() - lastAttemptTime > requestInterval) {
// if you're not connected, and two minutes have passed since
// your last connection, then attempt to connect again:
connectToServer();
}
}
void connectToServer() {
// attempt to connect, and wait a millisecond:
Serial.println("connecting to server...");
if (client.connect(server, 80)) {
Serial.println("making HTTP request...");
// make HTTP GET request to twitter:
client.println("GET /1/statuses/user_timeline.xml?screen_name=arduino HTTP/1.1");
client.println("Host:api.twitter.com");
client.println("Connection:close");
client.println();
}
// note the time of this connect attempt:
lastAttemptTime = millis();
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

View File

@@ -1,120 +0,0 @@
/*
Web client
This sketch connects to a website (http://www.google.com)
using a WiFi shield.
This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.
This example is written for a network using WPA encryption. For
WEP or WPA, change the Wifi.begin() call accordingly.
Circuit:
* WiFi shield attached
created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
*/
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "secretPassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
IPAddress server(173,194,73,105); // numeric IP for Google (no DNS)
//char server[] = "www.google.com"; // name address for Google (using DNS)
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /search?q=arduino HTTP/1.1");
client.println("Host:www.google.com");
client.println("Connection: close");
client.println();
}
}
void loop() {
// if there are incoming bytes available
// from the server, read them and print them:
while (client.available()) {
char c = client.read();
Serial.write(c);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting from server.");
client.stop();
// do nothing forevermore:
while(true);
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

Some files were not shown because too many files have changed in this diff Show More