Merge remote-tracking branch 'upstream/master'

pull/349/head
tkuyucu 2014-06-10 14:55:44 +02:00
commit 64b6589439
765 changed files with 158970 additions and 23178 deletions

3
.gitignore vendored
View File

@ -60,3 +60,6 @@ debug.log
# Ignore OS X Desktop Services Store files # Ignore OS X Desktop Services Store files
.DS_Store .DS_Store
# Orig diff files
*.orig

View File

@ -22,6 +22,8 @@ Documentation
Supported Microcontrollers and Boards Supported Microcontrollers and Boards
------------------------------------- -------------------------------------
View all on the [mbed Platforms](https://mbed.org/platforms/) page.
NXP: NXP:
* [mbed LPC1768](http://mbed.org/platforms/mbed-LPC1768/) (Cortex-M3) * [mbed LPC1768](http://mbed.org/platforms/mbed-LPC1768/) (Cortex-M3)
* [u-blox C027 LPC1768](http://mbed.org/platforms/u-blox-C027/) (Cortex-M3) * [u-blox C027 LPC1768](http://mbed.org/platforms/u-blox-C027/) (Cortex-M3)
@ -36,19 +38,24 @@ NXP:
* [LPC1114](http://mbed.org/platforms/LPC1114FN28/) (Cortex-M0) * [LPC1114](http://mbed.org/platforms/LPC1114FN28/) (Cortex-M0)
* LPC11C24 (Cortex-M0) * LPC11C24 (Cortex-M0)
* [LPC1549](https://mbed.org/platforms/LPCXpresso1549/) (Cortex-M3) * [LPC1549](https://mbed.org/platforms/LPCXpresso1549/) (Cortex-M3)
* [LPC800-MAX](https://mbed.org/platforms/NXP-LPC800-MAX/) (Cortex-M0+)
* [DipCortex-M0](https://mbed.org/platforms/DipCortex-M0/) (Cortex-M0)
* [DipCortex-M3](https://mbed.org/platforms/DipCortex-M3/) (Cortex-M3)
* [BlueBoard-LPC11U24](https://mbed.org/platforms/BlueBoard-LPC11U24/) (Cortex-M0)
Freescale: Freescale:
* FRDM-K20D50M (Cortex-M4) * FRDM-K20D50M (Cortex-M4)
* [FRDM-KL05Z](https://mbed.org/platforms/FRDM-KL05Z/) (Cortex-M0+) * [FRDM-KL05Z](https://mbed.org/platforms/FRDM-KL05Z/) (Cortex-M0+)
* [FRDM-KL25Z](http://mbed.org/platforms/KL25Z/) (Cortex-M0+) * [FRDM-KL25Z](http://mbed.org/platforms/KL25Z/) (Cortex-M0+)
* [FRDM-KL46Z](https://mbed.org/platforms/FRDM-KL46Z/) (Cortex-M0+) * [FRDM-KL46Z](https://mbed.org/platforms/FRDM-KL46Z/) (Cortex-M0+)
* FRDM-K64F (Cortex-M4) * [FRDM-K64F](https://mbed.org/platforms/FRDM-K64F/) (Cortex-M4)
STMicroelectronics: STMicroelectronics:
* [Nucleo-F103RB](https://mbed.org/platforms/ST-Nucleo-F103RB/) (Cortex-M3) * [Nucleo-F103RB](https://mbed.org/platforms/ST-Nucleo-F103RB/) (Cortex-M3)
* [Nucleo-L152RE](https://mbed.org/platforms/ST-Nucleo-L152RE/) (Cortex-M3) * [Nucleo-L152RE](https://mbed.org/platforms/ST-Nucleo-L152RE/) (Cortex-M3)
* [Nucleo-F030R8](https://mbed.org/platforms/ST-Nucleo-F030R8/) (Cortex-M0) * [Nucleo-F030R8](https://mbed.org/platforms/ST-Nucleo-F030R8/) (Cortex-M0)
* [Nucleo-F401RE](https://mbed.org/platforms/ST-Nucleo-F401RE/) (Cortex-M4) * [Nucleo-F401RE](https://mbed.org/platforms/ST-Nucleo-F401RE/) (Cortex-M4)
* [Nucleo-F302R8](https://mbed.org/platforms/ST-Nucleo-F302R8/) (Cortex-M4)
* STM32F4XX (Cortex-M4F) * STM32F4XX (Cortex-M4F)
* STM32F3XX (Cortex-M4F) * STM32F3XX (Cortex-M4F)
* STM32F0-Discovery (Cortex-M0) * STM32F0-Discovery (Cortex-M0)

View File

@ -50,7 +50,7 @@
* *
* int main() { * int main() {
* int16_t buf[AUDIO_LENGTH_PACKET/2]; * int16_t buf[AUDIO_LENGTH_PACKET/2];
* *
* while (1) { * while (1) {
* // read an audio packet * // read an audio packet
* audio.read((uint8_t *)buf); * audio.read((uint8_t *)buf);
@ -88,7 +88,7 @@ public:
* @returns volume * @returns volume
*/ */
float getVolume(); float getVolume();
/** /**
* Read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Blocking * Read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Blocking
* *
@ -97,7 +97,7 @@ public:
* @returns true if successfull * @returns true if successfull
*/ */
bool read(uint8_t * buf); bool read(uint8_t * buf);
/** /**
* Try to read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Non Blocking * Try to read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Non Blocking
* *
@ -106,7 +106,7 @@ public:
* @returns true if successfull * @returns true if successfull
*/ */
bool readNB(uint8_t * buf); bool readNB(uint8_t * buf);
/** /**
* Write an audio packet. During a frame, only a single writing (you can't write and read an audio packet during the same frame)can be done using this method. * Write an audio packet. During a frame, only a single writing (you can't write and read an audio packet during the same frame)can be done using this method.
* *
@ -114,7 +114,7 @@ public:
* @returns true if successful * @returns true if successful
*/ */
bool write(uint8_t * buf); bool write(uint8_t * buf);
/** /**
* Write and read an audio packet at the same time (on the same frame) * Write and read an audio packet at the same time (on the same frame)
* *
@ -123,7 +123,7 @@ public:
* @returns true if successful * @returns true if successful
*/ */
bool readWrite(uint8_t * buf_read, uint8_t * buf_write); bool readWrite(uint8_t * buf_read, uint8_t * buf_write);
/** attach a handler to update the volume /** attach a handler to update the volume
* *
@ -212,12 +212,12 @@ protected:
* Callback called on each Start of Frame event * Callback called on each Start of Frame event
*/ */
virtual void SOF(int frameNumber); virtual void SOF(int frameNumber);
/* /*
* Callback called when a packet is received * Callback called when a packet is received
*/ */
virtual bool EP3_OUT_callback(); virtual bool EP3_OUT_callback();
/* /*
* Callback called when a packet has been sent * Callback called when a packet has been sent
*/ */
@ -227,13 +227,13 @@ private:
// stream available ? // stream available ?
volatile bool available; volatile bool available;
// interrupt OUT has been received // interrupt OUT has been received
volatile bool interruptOUT; volatile bool interruptOUT;
// interrupt IN has been received // interrupt IN has been received
volatile bool interruptIN; volatile bool interruptIN;
// audio packet has been written // audio packet has been written
volatile bool writeIN; volatile bool writeIN;
@ -248,7 +248,7 @@ private:
// mono, stereo,... // mono, stereo,...
uint8_t channel_nb_in; uint8_t channel_nb_in;
uint8_t channel_nb_out; uint8_t channel_nb_out;
// channel config: master, left, right // channel config: master, left, right
uint8_t channel_config_in; uint8_t channel_config_in;
uint8_t channel_config_out; uint8_t channel_config_out;
@ -270,16 +270,16 @@ private:
// Buffer containing one audio packet (to be read) // Buffer containing one audio packet (to be read)
volatile uint8_t * buf_stream_in; volatile uint8_t * buf_stream_in;
// Buffer containing one audio packet (to be written) // Buffer containing one audio packet (to be written)
volatile uint8_t * buf_stream_out; volatile uint8_t * buf_stream_out;
// callback to update volume // callback to update volume
FunctionPointer updateVol; FunctionPointer updateVol;
// boolean showing that the SOF handler has been called. Useful for readNB. // boolean showing that the SOF handler has been called. Useful for readNB.
volatile bool SOF_handler; volatile bool SOF_handler;
volatile float volume; volatile float volume;
}; };

View File

@ -32,7 +32,7 @@
/*string offset*/ /*string offset*/
#define STRING_OFFSET_LANGID (0) #define STRING_OFFSET_LANGID (0)
#define STRING_OFFSET_IMANUFACTURER (1) #define STRING_OFFSET_IMANUFACTURER (1)
#define STRING_OFFSET_IPRODUCT (2) #define STRING_OFFSET_IPRODUCT (2)
#define STRING_OFFSET_ISERIAL (3) #define STRING_OFFSET_ISERIAL (3)

View File

@ -106,7 +106,7 @@ bool USBDevice::requestGetDescriptor(void)
transfer.ptr = stringImanufacturerDesc(); transfer.ptr = stringImanufacturerDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
case STRING_OFFSET_IPRODUCT: case STRING_OFFSET_IPRODUCT:
#ifdef DEBUG #ifdef DEBUG
printf("3\r\n"); printf("3\r\n");
@ -115,7 +115,7 @@ bool USBDevice::requestGetDescriptor(void)
transfer.ptr = stringIproductDesc(); transfer.ptr = stringIproductDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
case STRING_OFFSET_ISERIAL: case STRING_OFFSET_ISERIAL:
#ifdef DEBUG #ifdef DEBUG
printf("4\r\n"); printf("4\r\n");
@ -124,7 +124,7 @@ bool USBDevice::requestGetDescriptor(void)
transfer.ptr = stringIserialDesc(); transfer.ptr = stringIserialDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
case STRING_OFFSET_ICONFIGURATION: case STRING_OFFSET_ICONFIGURATION:
#ifdef DEBUG #ifdef DEBUG
printf("5\r\n"); printf("5\r\n");
@ -133,7 +133,7 @@ bool USBDevice::requestGetDescriptor(void)
transfer.ptr = stringIConfigurationDesc(); transfer.ptr = stringIConfigurationDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
case STRING_OFFSET_IINTERFACE: case STRING_OFFSET_IINTERFACE:
#ifdef DEBUG #ifdef DEBUG
printf("6\r\n"); printf("6\r\n");
@ -142,7 +142,7 @@ bool USBDevice::requestGetDescriptor(void)
transfer.ptr = stringIinterfaceDesc(); transfer.ptr = stringIinterfaceDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
} }
break; break;
case INTERFACE_DESCRIPTOR: case INTERFACE_DESCRIPTOR:
@ -357,7 +357,7 @@ bool USBDevice::requestSetInterface(void)
{ {
success = true; success = true;
currentInterface = transfer.setup.wIndex; currentInterface = transfer.setup.wIndex;
currentAlternate = transfer.setup.wValue; currentAlternate = transfer.setup.wValue;
} }
return success; return success;
} }
@ -473,12 +473,12 @@ bool USBDevice::requestGetStatus(void)
if (success) if (success)
{ {
/* Send the status */ /* Send the status */
transfer.ptr = (uint8_t *)&status; /* Assumes little endian */ transfer.ptr = (uint8_t *)&status; /* Assumes little endian */
transfer.remaining = sizeof(status); transfer.remaining = sizeof(status);
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
} }
return success; return success;
} }
@ -546,7 +546,7 @@ bool USBDevice::controlSetup(void)
transfer.direction = 0; transfer.direction = 0;
transfer.zlp = false; transfer.zlp = false;
transfer.notify = false; transfer.notify = false;
#ifdef DEBUG #ifdef DEBUG
printf("dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n",transfer.setup.bmRequestType.dataTransferDirection, printf("dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n",transfer.setup.bmRequestType.dataTransferDirection,
transfer.setup.bmRequestType.Type, transfer.setup.bmRequestType.Type,
@ -593,7 +593,7 @@ bool USBDevice::controlSetup(void)
} }
else else
{ {
/* OUT data stage is required */ /* OUT data stage is required */
if (transfer.direction != HOST_TO_DEVICE) if (transfer.direction != HOST_TO_DEVICE)
{ {
@ -707,7 +707,7 @@ void USBDevice::connect(bool blocking)
{ {
/* Connect device */ /* Connect device */
USBHAL::connect(); USBHAL::connect();
if (blocking) { if (blocking) {
/* Block if not configured */ /* Block if not configured */
while (!configured()); while (!configured());
@ -793,8 +793,8 @@ void USBDevice::suspendStateChanged(unsigned int suspended)
USBDevice::USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release){ USBDevice::USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release){
VENDOR_ID = vendor_id; VENDOR_ID = vendor_id;
PRODUCT_ID = product_id; PRODUCT_ID = product_id;
PRODUCT_RELEASE = product_release; PRODUCT_RELEASE = product_release;
/* Set initial device state */ /* Set initial device state */
@ -818,12 +818,12 @@ bool USBDevice::write(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_
{ {
return false; return false;
} }
if(!configured()) { if(!configured()) {
return false; return false;
} }
/* Send report */ /* Send report */
result = endpointWrite(endpoint, buffer, size); result = endpointWrite(endpoint, buffer, size);
@ -849,7 +849,7 @@ bool USBDevice::writeNB(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint3
{ {
return false; return false;
} }
if(!configured()) { if(!configured()) {
return false; return false;
} }
@ -872,7 +872,7 @@ bool USBDevice::writeNB(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint3
bool USBDevice::readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize) bool USBDevice::readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize)
{ {
EP_STATUS result; EP_STATUS result;
if(!configured()) { if(!configured()) {
return false; return false;
} }
@ -889,13 +889,13 @@ bool USBDevice::readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint
bool USBDevice::readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize) bool USBDevice::readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize)
{ {
EP_STATUS result; EP_STATUS result;
if(!configured()) { if(!configured()) {
return false; return false;
} }
result = endpointReadResult(endpoint, buffer, size); result = endpointReadResult(endpoint, buffer, size);
return (result == EP_COMPLETED); return (result == EP_COMPLETED);
} }

View File

@ -27,26 +27,26 @@ class USBDevice: public USBHAL
{ {
public: public:
USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release); USBDevice(uint16_t vendor_id, uint16_t product_id, uint16_t product_release);
/* /*
* Check if the device is configured * Check if the device is configured
* *
* @returns true if configured, false otherwise * @returns true if configured, false otherwise
*/ */
bool configured(void); bool configured(void);
/* /*
* Connect a device * Connect a device
* *
* @param blocking: block if not configured * @param blocking: block if not configured
*/ */
void connect(bool blocking = true); void connect(bool blocking = true);
/* /*
* Disconnect a device * Disconnect a device
*/ */
void disconnect(void); void disconnect(void);
/* /*
* Add an endpoint * Add an endpoint
* *
@ -65,7 +65,7 @@ public:
* @return true if successful * @return true if successful
*/ */
bool readStart(uint8_t endpoint, uint32_t maxSize); bool readStart(uint8_t endpoint, uint32_t maxSize);
/* /*
* Read a certain endpoint. Before calling this function, USBUSBDevice_readStart * Read a certain endpoint. Before calling this function, USBUSBDevice_readStart
* must be called. * must be called.
@ -79,20 +79,20 @@ public:
* @returns true if successful * @returns true if successful
*/ */
bool readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize); bool readEP(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize);
/* /*
* Read a certain endpoint. * Read a certain endpoint.
* *
* Warning: non blocking * Warning: non blocking
* *
* @param endpoint endpoint which will be read * @param endpoint endpoint which will be read
* @param buffer buffer will be filled with the data received (if data are available) * @param buffer buffer will be filled with the data received (if data are available)
* @param size the number of bytes read will be stored in *size * @param size the number of bytes read will be stored in *size
* @param maxSize the maximum length that can be read * @param maxSize the maximum length that can be read
* @returns true if successful * @returns true if successful
*/ */
bool readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize); bool readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, uint32_t maxSize);
/* /*
* Write a certain endpoint. * Write a certain endpoint.
* *
@ -104,8 +104,8 @@ public:
* @param maxSize the maximum length that can be written on this endpoint * @param maxSize the maximum length that can be written on this endpoint
*/ */
bool write(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_t maxSize); bool write(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_t maxSize);
/* /*
* Write a certain endpoint. * Write a certain endpoint.
* *
@ -118,14 +118,14 @@ public:
*/ */
bool writeNB(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_t maxSize); bool writeNB(uint8_t endpoint, uint8_t * buffer, uint32_t size, uint32_t maxSize);
/* /*
* Called by USBDevice layer on bus reset. Warning: Called in ISR context * Called by USBDevice layer on bus reset. Warning: Called in ISR context
* *
* May be used to reset state * May be used to reset state
*/ */
virtual void USBCallback_busReset(void) {}; virtual void USBCallback_busReset(void) {};
/* /*
* Called by USBDevice on Endpoint0 request. Warning: Called in ISR context * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
* This is used to handle extensions to standard requests * This is used to handle extensions to standard requests
@ -133,8 +133,8 @@ public:
* *
* @returns true if class handles this request * @returns true if class handles this request
*/ */
virtual bool USBCallback_request() { return false; }; virtual bool USBCallback_request() { return false; };
/* /*
* Called by USBDevice on Endpoint0 request completion * Called by USBDevice on Endpoint0 request completion
* if the 'notify' flag has been set to true. Warning: Called in ISR context * if the 'notify' flag has been set to true. Warning: Called in ISR context
@ -146,7 +146,7 @@ public:
* @param length length of this buffer * @param length length of this buffer
*/ */
virtual void USBCallback_requestCompleted(uint8_t * buf, uint32_t length) {}; virtual void USBCallback_requestCompleted(uint8_t * buf, uint32_t length) {};
/* /*
* Called by USBDevice layer. Set configuration of the device. * Called by USBDevice layer. Set configuration of the device.
* For instance, you can add all endpoints that you need on this function. * For instance, you can add all endpoints that you need on this function.
@ -154,7 +154,7 @@ public:
* @param configuration Number of the configuration * @param configuration Number of the configuration
*/ */
virtual bool USBCallback_setConfiguration(uint8_t configuration) { return false; }; virtual bool USBCallback_setConfiguration(uint8_t configuration) { return false; };
/* /*
* Called by USBDevice layer. Set interface/alternate of the device. * Called by USBDevice layer. Set interface/alternate of the device.
* *
@ -170,63 +170,63 @@ public:
* @returns pointer to the device descriptor * @returns pointer to the device descriptor
*/ */
virtual uint8_t * deviceDesc(); virtual uint8_t * deviceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *
* @returns pointer to the configuration descriptor * @returns pointer to the configuration descriptor
*/ */
virtual uint8_t * configurationDesc(){return NULL;}; virtual uint8_t * configurationDesc(){return NULL;};
/* /*
* Get string lang id descriptor * Get string lang id descriptor
* *
* @return pointer to the string lang id descriptor * @return pointer to the string lang id descriptor
*/ */
virtual uint8_t * stringLangidDesc(); virtual uint8_t * stringLangidDesc();
/* /*
* Get string manufacturer descriptor * Get string manufacturer descriptor
* *
* @returns pointer to the string manufacturer descriptor * @returns pointer to the string manufacturer descriptor
*/ */
virtual uint8_t * stringImanufacturerDesc(); virtual uint8_t * stringImanufacturerDesc();
/* /*
* Get string product descriptor * Get string product descriptor
* *
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual uint8_t * stringIproductDesc();
/* /*
* Get string serial descriptor * Get string serial descriptor
* *
* @returns pointer to the string serial descriptor * @returns pointer to the string serial descriptor
*/ */
virtual uint8_t * stringIserialDesc(); virtual uint8_t * stringIserialDesc();
/* /*
* Get string configuration descriptor * Get string configuration descriptor
* *
* @returns pointer to the string configuration descriptor * @returns pointer to the string configuration descriptor
*/ */
virtual uint8_t * stringIConfigurationDesc(); virtual uint8_t * stringIConfigurationDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual uint8_t * stringIinterfaceDesc();
/* /*
* Get the length of the report descriptor * Get the length of the report descriptor
* *
* @returns length of the report descriptor * @returns length of the report descriptor
*/ */
virtual uint16_t reportDescLength() { return 0; }; virtual uint16_t reportDescLength() { return 0; };
protected: protected:
@ -238,7 +238,7 @@ protected:
virtual void suspendStateChanged(unsigned int suspended); virtual void suspendStateChanged(unsigned int suspended);
uint8_t * findDescriptor(uint8_t descriptorType); uint8_t * findDescriptor(uint8_t descriptorType);
CONTROL_TRANSFER * getTransferPtr(void); CONTROL_TRANSFER * getTransferPtr(void);
uint16_t VENDOR_ID; uint16_t VENDOR_ID;
uint16_t PRODUCT_ID; uint16_t PRODUCT_ID;
uint16_t PRODUCT_RELEASE; uint16_t PRODUCT_RELEASE;
@ -262,7 +262,7 @@ private:
CONTROL_TRANSFER transfer; CONTROL_TRANSFER transfer;
USB_DEVICE device; USB_DEVICE device;
uint16_t currentInterface; uint16_t currentInterface;
uint8_t currentAlternate; uint8_t currentAlternate;
}; };

View File

@ -39,7 +39,7 @@ typedef enum {
/* Include configuration for specific target */ /* Include configuration for specific target */
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088) #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088)
#include "USBEndpoints_LPC17_LPC23.h" #include "USBEndpoints_LPC17_LPC23.h"
#elif defined(TARGET_LPC11UXX) || defined(TARGET_LPC1347) #elif defined(TARGET_LPC11UXX) || defined(TARGET_LPC1347) || defined (TARGET_LPC11U6X)
#include "USBEndpoints_LPC11U.h" #include "USBEndpoints_LPC11U.h"
#elif defined(TARGET_KL25Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F) #elif defined(TARGET_KL25Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F)
#include "USBEndpoints_KL25Z.h" #include "USBEndpoints_KL25Z.h"

View File

@ -23,38 +23,38 @@
/* Endpoint No. */ /* Endpoint No. */
/* ---------------- */ /* ---------------- */
#define EP0OUT (0) #define EP0OUT (0)
#define EP0IN (1) #define EP0IN (1)
#define EP1OUT (2) #define EP1OUT (2)
#define EP1IN (3) #define EP1IN (3)
#define EP2OUT (4) #define EP2OUT (4)
#define EP2IN (5) #define EP2IN (5)
#define EP3OUT (6) #define EP3OUT (6)
#define EP3IN (7) #define EP3IN (7)
#define EP4OUT (8) #define EP4OUT (8)
#define EP4IN (9) #define EP4IN (9)
#define EP5OUT (10) #define EP5OUT (10)
#define EP5IN (11) #define EP5IN (11)
#define EP6OUT (12) #define EP6OUT (12)
#define EP6IN (13) #define EP6IN (13)
#define EP7OUT (14) #define EP7OUT (14)
#define EP7IN (15) #define EP7IN (15)
#define EP8OUT (16) #define EP8OUT (16)
#define EP8IN (17) #define EP8IN (17)
#define EP9OUT (18) #define EP9OUT (18)
#define EP9IN (19) #define EP9IN (19)
#define EP10OUT (20) #define EP10OUT (20)
#define EP10IN (21) #define EP10IN (21)
#define EP11OUT (22) #define EP11OUT (22)
#define EP11IN (23) #define EP11IN (23)
#define EP12OUT (24) #define EP12OUT (24)
#define EP12IN (25) #define EP12IN (25)
#define EP13OUT (26) #define EP13OUT (26)
#define EP13IN (27) #define EP13IN (27)
#define EP14OUT (28) #define EP14OUT (28)
#define EP14IN (29) #define EP14IN (29)
#define EP15OUT (30) #define EP15OUT (30)
#define EP15IN (31) #define EP15IN (31)
/* Maximum Packet sizes */ /* Maximum Packet sizes */

View File

@ -58,7 +58,7 @@ public:
bool realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options); bool realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options);
bool getEndpointStallState(unsigned char endpoint); bool getEndpointStallState(unsigned char endpoint);
uint32_t endpointReadcore(uint8_t endpoint, uint8_t *buffer); uint32_t endpointReadcore(uint8_t endpoint, uint8_t *buffer);
protected: protected:
virtual void busReset(void){}; virtual void busReset(void){};
virtual void EP0setupCallback(void){}; virtual void EP0setupCallback(void){};
@ -67,7 +67,7 @@ protected:
virtual void connectStateChanged(unsigned int connected){}; virtual void connectStateChanged(unsigned int connected){};
virtual void suspendStateChanged(unsigned int suspended){}; virtual void suspendStateChanged(unsigned int suspended){};
virtual void SOF(int frameNumber){}; virtual void SOF(int frameNumber){};
virtual bool EP1_OUT_callback(){return false;}; virtual bool EP1_OUT_callback(){return false;};
virtual bool EP1_IN_callback(){return false;}; virtual bool EP1_IN_callback(){return false;};
virtual bool EP2_OUT_callback(){return false;}; virtual bool EP2_OUT_callback(){return false;};
@ -102,7 +102,7 @@ protected:
virtual bool EP15_IN_callback(){return false;}; virtual bool EP15_IN_callback(){return false;};
#endif #endif
#endif #endif
private: private:
void usbisr(void); void usbisr(void);
static void _usbisr(void); static void _usbisr(void);
@ -116,6 +116,6 @@ private:
bool (USBHAL::*epCallback[32 - 2])(void); bool (USBHAL::*epCallback[32 - 2])(void);
#endif #endif
}; };
#endif #endif

View File

@ -16,11 +16,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#if defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC1347) #if defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC1347) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPC11U68)
#if defined(TARGET_LPC1347) #if defined(TARGET_LPC1347)
#define USB_IRQ USB_IRQ_IRQn #define USB_IRQ USB_IRQ_IRQn
#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPC11U68)
#define USB_IRQ USB_IRQn #define USB_IRQ USB_IRQn
#endif #endif
@ -134,7 +134,7 @@ void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) {
USBHAL::USBHAL(void) { USBHAL::USBHAL(void) {
NVIC_DisableIRQ(USB_IRQ); NVIC_DisableIRQ(USB_IRQ);
// fill in callback array // fill in callback array
epCallback[0] = &USBHAL::EP1_OUT_callback; epCallback[0] = &USBHAL::EP1_OUT_callback;
epCallback[1] = &USBHAL::EP1_IN_callback; epCallback[1] = &USBHAL::EP1_IN_callback;
@ -145,11 +145,11 @@ USBHAL::USBHAL(void) {
epCallback[6] = &USBHAL::EP4_OUT_callback; epCallback[6] = &USBHAL::EP4_OUT_callback;
epCallback[7] = &USBHAL::EP4_IN_callback; epCallback[7] = &USBHAL::EP4_IN_callback;
#if defined(TARGET_LPC11U35_401) #if defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501)
// USB_VBUS input with pull-down // USB_VBUS input with pull-down
LPC_IOCON->PIO0_3 = 0x00000009; LPC_IOCON->PIO0_3 = 0x00000009;
#endif #endif
// nUSB_CONNECT output // nUSB_CONNECT output
LPC_IOCON->PIO0_6 = 0x00000001; LPC_IOCON->PIO0_6 = 0x00000001;
@ -287,13 +287,13 @@ EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
bf = 0; bf = 0;
} }
} }
// if isochronous endpoint, T = 1 // if isochronous endpoint, T = 1
if(endpointState[endpoint].options & ISOCHRONOUS) if(endpointState[endpoint].options & ISOCHRONOUS)
{ {
flags |= CMDSTS_T; flags |= CMDSTS_T;
} }
//Active the endpoint for reading //Active the endpoint for reading
ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \ ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
| CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags; | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags;
@ -408,7 +408,7 @@ EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
uint32_t bf; uint32_t bf;
// Validate parameters // Validate parameters
if (endpoint > LAST_PHYSICAL_ENDPOINT) { if (endpoint > LAST_PHYSICAL_ENDPOINT) {
return EP_INVALID; return EP_INVALID;
@ -680,7 +680,7 @@ void USBHAL::usbisr(void) {
// EP0IN ACK event (IN data sent) // EP0IN ACK event (IN data sent)
EP0in(); EP0in();
} }
for (uint8_t num = 2; num < 5*2; num++) { for (uint8_t num = 2; num < 5*2; num++) {
if (LPC_USB->INTSTAT & EP(num)) { if (LPC_USB->INTSTAT & EP(num)) {
LPC_USB->INTSTAT = EP(num); LPC_USB->INTSTAT = EP(num);

View File

@ -279,7 +279,7 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
SIEselectEndpoint(endpoint); SIEselectEndpoint(endpoint);
SIEclearBuffer(); SIEclearBuffer();
} }
return size; return size;
} }
@ -327,7 +327,7 @@ static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size)
USBHAL::USBHAL(void) { USBHAL::USBHAL(void) {
// Disable IRQ // Disable IRQ
NVIC_DisableIRQ(USB_IRQn); NVIC_DisableIRQ(USB_IRQn);
// fill in callback array // fill in callback array
epCallback[0] = &USBHAL::EP1_OUT_callback; epCallback[0] = &USBHAL::EP1_OUT_callback;
epCallback[1] = &USBHAL::EP1_IN_callback; epCallback[1] = &USBHAL::EP1_IN_callback;
@ -466,7 +466,7 @@ EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_
if (!(epComplete & EP(endpoint))) if (!(epComplete & EP(endpoint)))
return EP_PENDING; return EP_PENDING;
} }
*bytesRead = endpointReadcore(endpoint, buffer); *bytesRead = endpointReadcore(endpoint, buffer);
epComplete &= ~EP(endpoint); epComplete &= ~EP(endpoint);
return EP_COMPLETED; return EP_COMPLETED;
@ -606,7 +606,7 @@ void USBHAL::usbisr(void) {
LPC_USB->USBDevIntClr = EP_SLOW; LPC_USB->USBDevIntClr = EP_SLOW;
EP0in(); EP0in();
} }
for (uint8_t num = 2; num < 16*2; num++) { for (uint8_t num = 2; num < 16*2; num++) {
if (LPC_USB->USBEpIntSt & EP(num)) { if (LPC_USB->USBEpIntSt & EP(num)) {
selectEndpointClearInterrupt(num); selectEndpointClearInterrupt(num);

View File

@ -280,7 +280,7 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
SIEselectEndpoint(endpoint); SIEselectEndpoint(endpoint);
SIEclearBuffer(); SIEclearBuffer();
} }
return size; return size;
} }
@ -328,7 +328,7 @@ static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size)
USBHAL::USBHAL(void) { USBHAL::USBHAL(void) {
// Disable IRQ // Disable IRQ
NVIC_DisableIRQ(USB_IRQn); NVIC_DisableIRQ(USB_IRQn);
// fill in callback array // fill in callback array
epCallback[0] = &USBHAL::EP1_OUT_callback; epCallback[0] = &USBHAL::EP1_OUT_callback;
epCallback[1] = &USBHAL::EP1_IN_callback; epCallback[1] = &USBHAL::EP1_IN_callback;
@ -367,7 +367,7 @@ USBHAL::USBHAL(void) {
// Enable USB clocks // Enable USB clocks
LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN; LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN;
while ((LPC_USB->USBClkSt & (DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN)) != (DEV_CLK_ON | AHB_CLK_ON | PORT_CLK_EN)); while ((LPC_USB->USBClkSt & (DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN)) != (DEV_CLK_ON | AHB_CLK_ON | PORT_CLK_EN));
// Select port USB2 // Select port USB2
LPC_USB->StCtrl |= 3; LPC_USB->StCtrl |= 3;
@ -375,13 +375,13 @@ USBHAL::USBHAL(void) {
// Configure pin P0.31 to be USB2 // Configure pin P0.31 to be USB2
LPC_IOCON->P0_31 &= ~0x07; LPC_IOCON->P0_31 &= ~0x07;
LPC_IOCON->P0_31 |= 0x01; LPC_IOCON->P0_31 |= 0x01;
// Disconnect USB device // Disconnect USB device
SIEdisconnect(); SIEdisconnect();
// Configure pin P0.14 to be Connect // Configure pin P0.14 to be Connect
LPC_IOCON->P0_14 &= ~0x07; LPC_IOCON->P0_14 &= ~0x07;
LPC_IOCON->P0_14 |= 0x03; LPC_IOCON->P0_14 |= 0x03;
// Connect must be low for at least 2.5uS // Connect must be low for at least 2.5uS
wait(0.3); wait(0.3);
@ -471,7 +471,7 @@ EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_
if (!(epComplete & EP(endpoint))) if (!(epComplete & EP(endpoint)))
return EP_PENDING; return EP_PENDING;
} }
*bytesRead = endpointReadcore(endpoint, buffer); *bytesRead = endpointReadcore(endpoint, buffer);
epComplete &= ~EP(endpoint); epComplete &= ~EP(endpoint);
return EP_COMPLETED; return EP_COMPLETED;
@ -611,7 +611,7 @@ void USBHAL::usbisr(void) {
LPC_USB->DevIntClr = EP_SLOW; LPC_USB->DevIntClr = EP_SLOW;
EP0in(); EP0in();
} }
for (uint8_t num = 2; num < 16*2; num++) { for (uint8_t num = 2; num < 16*2; num++) {
if (LPC_USB->EpIntSt & EP(num)) { if (LPC_USB->EpIntSt & EP(num)) {
selectEndpointClearInterrupt(num); selectEndpointClearInterrupt(num);

View File

@ -36,7 +36,7 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
return 0; return 0;
} }
USBHAL::USBHAL(void) { USBHAL::USBHAL(void) {
NVIC_DisableIRQ(OTG_FS_IRQn); NVIC_DisableIRQ(OTG_FS_IRQn);
epCallback[0] = &USBHAL::EP1_OUT_callback; epCallback[0] = &USBHAL::EP1_OUT_callback;
epCallback[1] = &USBHAL::EP1_IN_callback; epCallback[1] = &USBHAL::EP1_IN_callback;
@ -63,7 +63,7 @@ USBHAL::USBHAL(void) {
pin_mode(PA_9, OpenDrain); pin_mode(PA_9, OpenDrain);
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN; RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
// Enable interrupts // Enable interrupts
OTG_FS->GREGS.GAHBCFG |= (1 << 0); OTG_FS->GREGS.GAHBCFG |= (1 << 0);
@ -116,21 +116,21 @@ bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket,
uint32_t type; uint32_t type;
switch (endpoint) { switch (endpoint) {
case EP0IN: case EP0IN:
case EP0OUT: case EP0OUT:
type = 0; type = 0;
break; break;
case EPISO_IN: case EPISO_IN:
case EPISO_OUT: case EPISO_OUT:
type = 1; type = 1;
case EPBULK_IN: case EPBULK_IN:
case EPBULK_OUT: case EPBULK_OUT:
type = 2; type = 2;
break; break;
case EPINT_IN: case EPINT_IN:
case EPINT_OUT: case EPINT_OUT:
type = 3; type = 3;
break; break;
} }
// Generic in or out EP controls // Generic in or out EP controls
@ -154,7 +154,7 @@ bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket,
if (endpoint != EP0IN) { if (endpoint != EP0IN) {
control |= (1 << 28); // SD0PID control |= (1 << 28); // SD0PID
} }
control |= (epIndex << 22) | // TxFIFO index control |= (epIndex << 22) | // TxFIFO index
(1 << 27); // SNAK (1 << 27); // SNAK
OTG_FS->INEP_REGS[epIndex].DIEPCTL = control; OTG_FS->INEP_REGS[epIndex].DIEPCTL = control;
@ -166,7 +166,7 @@ bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket,
// Set the out EP specific control settings // Set the out EP specific control settings
control |= (1 << 26); // CNAK control |= (1 << 26); // CNAK
OTG_FS->OUTEP_REGS[epIndex].DOEPCTL = control; OTG_FS->OUTEP_REGS[epIndex].DOEPCTL = control;
// Unmask the interrupt // Unmask the interrupt
OTG_FS->DREGS.DAINTMSK |= (1 << (epIndex + 16)); OTG_FS->DREGS.DAINTMSK |= (1 << (epIndex + 16));
} }
@ -190,7 +190,7 @@ uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
for (uint32_t i = 0; i < length; i += 4) { for (uint32_t i = 0; i < length; i += 4) {
buffer32[i >> 2] = OTG_FS->FIFO[0][0]; buffer32[i >> 2] = OTG_FS->FIFO[0][0];
} }
rxFifoCount = 0; rxFifoCount = 0;
return length; return length;
} }
@ -266,7 +266,7 @@ EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
return EP_COMPLETED; return EP_COMPLETED;
} }
return EP_PENDING; return EP_PENDING;
} }
void USBHAL::stallEndpoint(uint8_t endpoint) { void USBHAL::stallEndpoint(uint8_t endpoint) {
@ -282,7 +282,7 @@ void USBHAL::stallEndpoint(uint8_t endpoint) {
} }
void USBHAL::unstallEndpoint(uint8_t endpoint) { void USBHAL::unstallEndpoint(uint8_t endpoint) {
} }
bool USBHAL::getEndpointStallState(uint8_t endpoint) { bool USBHAL::getEndpointStallState(uint8_t endpoint) {

View File

@ -16,8 +16,8 @@
* *
* http://www.st.com/software_license_agreement_liberty_v2 * http://www.st.com/software_license_agreement_liberty_v2
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
@ -70,7 +70,7 @@ typedef struct // 800h
} }
USB_OTG_DREGS; USB_OTG_DREGS;
typedef struct typedef struct
{ {
__IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/ __IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/
uint32_t Reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/ uint32_t Reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/
@ -83,7 +83,7 @@ typedef struct
} }
USB_OTG_INEPREGS; USB_OTG_INEPREGS;
typedef struct typedef struct
{ {
__IO uint32_t DOEPCTL; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/ __IO uint32_t DOEPCTL; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/
uint32_t Reserved04; /* Reserved B00h + (ep_num * 20h) + 04h*/ uint32_t Reserved04; /* Reserved B00h + (ep_num * 20h) + 04h*/
@ -117,7 +117,7 @@ typedef struct
} }
USB_OTG_HC_REGS; USB_OTG_HC_REGS;
typedef struct typedef struct
{ {
USB_OTG_GREGS GREGS; USB_OTG_GREGS GREGS;
uint32_t RESERVED0[188]; uint32_t RESERVED0[188];

View File

@ -121,7 +121,7 @@ bool USBHID::USBCallback_request() {
success = true; success = true;
} }
break; break;
default: default:
break; break;
} }

View File

@ -70,8 +70,8 @@ public:
* @returns true if successful * @returns true if successful
*/ */
bool send(HID_REPORT *report); bool send(HID_REPORT *report);
/** /**
* Send a Report. warning: non blocking * Send a Report. warning: non blocking
* *
@ -79,7 +79,7 @@ public:
* @returns true if successful * @returns true if successful
*/ */
bool sendNB(HID_REPORT *report); bool sendNB(HID_REPORT *report);
/** /**
* Read a report: blocking * Read a report: blocking
* *
@ -87,7 +87,7 @@ public:
* @returns true if successful * @returns true if successful
*/ */
bool read(HID_REPORT * report); bool read(HID_REPORT * report);
/** /**
* Read a report: non blocking * Read a report: non blocking
* *
@ -98,7 +98,7 @@ public:
protected: protected:
uint16_t reportLength; uint16_t reportLength;
/* /*
* Get the Report descriptor * Get the Report descriptor
* *
@ -119,14 +119,14 @@ protected:
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual uint8_t * stringIproductDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual uint8_t * stringIinterfaceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *

View File

@ -183,7 +183,7 @@ const KEYMAP keymap[KEYMAP_SIZE] = {
{0x4a, 0}, /* HOME */ {0x4a, 0}, /* HOME */
{0x4b, 0}, /* PAGE_UP */ {0x4b, 0}, /* PAGE_UP */
{0x4e, 0}, /* PAGE_DOWN */ {0x4e, 0}, /* PAGE_DOWN */
{0x4f, 0}, /* RIGHT_ARROW */ {0x4f, 0}, /* RIGHT_ARROW */
{0x50, 0}, /* LEFT_ARROW */ {0x50, 0}, /* LEFT_ARROW */
{0x51, 0}, /* DOWN_ARROW */ {0x51, 0}, /* DOWN_ARROW */
@ -344,7 +344,7 @@ const KEYMAP keymap[KEYMAP_SIZE] = {
{0x4a, 0}, /* HOME */ {0x4a, 0}, /* HOME */
{0x4b, 0}, /* PAGE_UP */ {0x4b, 0}, /* PAGE_UP */
{0x4e, 0}, /* PAGE_DOWN */ {0x4e, 0}, /* PAGE_DOWN */
{0x4f, 0}, /* RIGHT_ARROW */ {0x4f, 0}, /* RIGHT_ARROW */
{0x50, 0}, /* LEFT_ARROW */ {0x50, 0}, /* LEFT_ARROW */
{0x51, 0}, /* DOWN_ARROW */ {0x51, 0}, /* DOWN_ARROW */
@ -424,10 +424,10 @@ bool USBKeyboard::EP1_OUT_callback() {
uint32_t bytesRead = 0; uint32_t bytesRead = 0;
uint8_t led[65]; uint8_t led[65];
USBDevice::readEP(EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE); USBDevice::readEP(EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE);
// we take led[1] because led[0] is the report ID // we take led[1] because led[0] is the report ID
lock_status = led[1] & 0x07; lock_status = led[1] & 0x07;
// We activate the endpoint to be able to recceive data // We activate the endpoint to be able to recceive data
if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
return false; return false;

View File

@ -53,7 +53,7 @@ enum FUNCTION_KEY {
KEY_F10, /* F10 key */ KEY_F10, /* F10 key */
KEY_F11, /* F11 key */ KEY_F11, /* F11 key */
KEY_F12, /* F12 key */ KEY_F12, /* F12 key */
KEY_PRINT_SCREEN, /* Print Screen key */ KEY_PRINT_SCREEN, /* Print Screen key */
KEY_SCROLL_LOCK, /* Scroll lock */ KEY_SCROLL_LOCK, /* Scroll lock */
KEY_CAPS_LOCK, /* caps lock */ KEY_CAPS_LOCK, /* caps lock */
@ -62,7 +62,7 @@ enum FUNCTION_KEY {
KEY_HOME, /* Home key */ KEY_HOME, /* Home key */
KEY_PAGE_UP, /* Page Up key */ KEY_PAGE_UP, /* Page Up key */
KEY_PAGE_DOWN, /* Page Down key */ KEY_PAGE_DOWN, /* Page Down key */
RIGHT_ARROW, /* Right arrow */ RIGHT_ARROW, /* Right arrow */
LEFT_ARROW, /* Left arrow */ LEFT_ARROW, /* Left arrow */
DOWN_ARROW, /* Down arrow */ DOWN_ARROW, /* Down arrow */

View File

@ -35,7 +35,7 @@ enum MOUSE_BUTTON
/* X and Y limits */ /* X and Y limits */
/* These values do not directly map to screen pixels */ /* These values do not directly map to screen pixels */
/* Zero may be interpreted as meaning 'no movement' */ /* Zero may be interpreted as meaning 'no movement' */
#define X_MIN_ABS (1) /*!< Minimum value on x-axis */ #define X_MIN_ABS (1) /*!< Minimum value on x-axis */
#define Y_MIN_ABS (1) /*!< Minimum value on y-axis */ #define Y_MIN_ABS (1) /*!< Minimum value on y-axis */
#define X_MAX_ABS (0x7fff) /*!< Maximum value on x-axis */ #define X_MAX_ABS (0x7fff) /*!< Maximum value on x-axis */
#define Y_MAX_ABS (0x7fff) /*!< Maximum value on y-axis */ #define Y_MAX_ABS (0x7fff) /*!< Maximum value on y-axis */
@ -85,7 +85,7 @@ enum MOUSE_TYPE
* uint16_t y_center = (Y_MAX_ABS - Y_MIN_ABS)/2; * uint16_t y_center = (Y_MAX_ABS - Y_MIN_ABS)/2;
* uint16_t x_screen = 0; * uint16_t x_screen = 0;
* uint16_t y_screen = 0; * uint16_t y_screen = 0;
* *
* uint32_t x_origin = x_center; * uint32_t x_origin = x_center;
* uint32_t y_origin = y_center; * uint32_t y_origin = y_center;
* uint32_t radius = 5000; * uint32_t radius = 5000;
@ -95,7 +95,7 @@ enum MOUSE_TYPE
* { * {
* x_screen = x_origin + cos((double)angle*3.14/180.0)*radius; * x_screen = x_origin + cos((double)angle*3.14/180.0)*radius;
* y_screen = y_origin + sin((double)angle*3.14/180.0)*radius; * y_screen = y_origin + sin((double)angle*3.14/180.0)*radius;
* *
* mouse.move(x_screen, y_screen); * mouse.move(x_screen, y_screen);
* angle += 3; * angle += 3;
* wait(0.01); * wait(0.01);
@ -107,7 +107,7 @@ enum MOUSE_TYPE
class USBMouse: public USBHID class USBMouse: public USBHID
{ {
public: public:
/** /**
* Constructor * Constructor
* *
@ -117,14 +117,14 @@ class USBMouse: public USBHID
* @param product_release Your preoduct_release (default: 0x0001) * @param product_release Your preoduct_release (default: 0x0001)
* *
*/ */
USBMouse(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0001, uint16_t product_release = 0x0001): USBMouse(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0001, uint16_t product_release = 0x0001):
USBHID(0, 0, vendor_id, product_id, product_release, false) USBHID(0, 0, vendor_id, product_id, product_release, false)
{ {
button = 0; button = 0;
this->mouse_type = mouse_type; this->mouse_type = mouse_type;
connect(); connect();
}; };
/** /**
* Write a state of the mouse * Write a state of the mouse
* *
@ -135,8 +135,8 @@ class USBMouse: public USBHID
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z); bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z);
/** /**
* Move the cursor to (x, y) * Move the cursor to (x, y)
* *
@ -145,7 +145,7 @@ class USBMouse: public USBHID
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool move(int16_t x, int16_t y); bool move(int16_t x, int16_t y);
/** /**
* Press one or several buttons * Press one or several buttons
* *
@ -153,7 +153,7 @@ class USBMouse: public USBHID
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool press(uint8_t button); bool press(uint8_t button);
/** /**
* Release one or several buttons * Release one or several buttons
* *
@ -161,22 +161,22 @@ class USBMouse: public USBHID
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool release(uint8_t button); bool release(uint8_t button);
/** /**
* Double click (MOUSE_LEFT) * Double click (MOUSE_LEFT)
* *
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool doubleClick(); bool doubleClick();
/** /**
* Click * Click
* *
* @param button state of the buttons ( ex: clic(MOUSE_LEFT)) * @param button state of the buttons ( ex: clic(MOUSE_LEFT))
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool click(uint8_t button); bool click(uint8_t button);
/** /**
* Scrolling * Scrolling
* *
@ -184,7 +184,7 @@ class USBMouse: public USBHID
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool scroll(int8_t z); bool scroll(int8_t z);
/* /*
* To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength. * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
* *
@ -199,7 +199,7 @@ class USBMouse: public USBHID
* @returns pointer to the configuration descriptor * @returns pointer to the configuration descriptor
*/ */
virtual uint8_t * configurationDesc(); virtual uint8_t * configurationDesc();
private: private:
MOUSE_TYPE mouse_type; MOUSE_TYPE mouse_type;
uint8_t button; uint8_t button;

View File

@ -178,7 +178,7 @@ const KEYMAP keymap[KEYMAP_SIZE] = {
{0x4a, 0}, /* HOME */ {0x4a, 0}, /* HOME */
{0x4b, 0}, /* PAGE_UP */ {0x4b, 0}, /* PAGE_UP */
{0x4e, 0}, /* PAGE_DOWN */ {0x4e, 0}, /* PAGE_DOWN */
{0x4f, 0}, /* RIGHT_ARROW */ {0x4f, 0}, /* RIGHT_ARROW */
{0x50, 0}, /* LEFT_ARROW */ {0x50, 0}, /* LEFT_ARROW */
{0x51, 0}, /* DOWN_ARROW */ {0x51, 0}, /* DOWN_ARROW */
@ -339,7 +339,7 @@ const KEYMAP keymap[KEYMAP_SIZE] = {
{0x4a, 0}, /* HOME */ {0x4a, 0}, /* HOME */
{0x4b, 0}, /* PAGE_UP */ {0x4b, 0}, /* PAGE_UP */
{0x4e, 0}, /* PAGE_DOWN */ {0x4e, 0}, /* PAGE_DOWN */
{0x4f, 0}, /* RIGHT_ARROW */ {0x4f, 0}, /* RIGHT_ARROW */
{0x50, 0}, /* LEFT_ARROW */ {0x50, 0}, /* LEFT_ARROW */
{0x51, 0}, /* DOWN_ARROW */ {0x51, 0}, /* DOWN_ARROW */
@ -552,10 +552,10 @@ bool USBMouseKeyboard::EP1_OUT_callback() {
uint32_t bytesRead = 0; uint32_t bytesRead = 0;
uint8_t led[65]; uint8_t led[65];
USBDevice::readEP(EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE); USBDevice::readEP(EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE);
// we take led[1] because led[0] is the report ID // we take led[1] because led[0] is the report ID
lock_status = led[1] & 0x07; lock_status = led[1] & 0x07;
// We activate the endpoint to be able to recceive data // We activate the endpoint to be able to recceive data
if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE))
return false; return false;
@ -696,7 +696,7 @@ bool USBMouseKeyboard::mediaControl(MEDIA_KEY key) {
report.length = 2; report.length = 2;
send(&report); send(&report);
report.data[0] = REPORT_ID_VOLUME; report.data[0] = REPORT_ID_VOLUME;
report.data[1] = 0; report.data[1] = 0;

View File

@ -28,7 +28,7 @@
#include "Stream.h" #include "Stream.h"
#include "USBHID.h" #include "USBHID.h"
/** /**
* USBMouseKeyboard example * USBMouseKeyboard example
* @code * @code
* *
@ -70,7 +70,7 @@
class USBMouseKeyboard: public USBHID, public Stream class USBMouseKeyboard: public USBHID, public Stream
{ {
public: public:
/** /**
* Constructor * Constructor
* *
@ -81,7 +81,7 @@ class USBMouseKeyboard: public USBHID, public Stream
* @param product_release Your preoduct_release (default: 0x0001) * @param product_release Your preoduct_release (default: 0x0001)
* *
*/ */
USBMouseKeyboard(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x0021, uint16_t product_id = 0x0011, uint16_t product_release = 0x0001): USBMouseKeyboard(MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x0021, uint16_t product_id = 0x0011, uint16_t product_release = 0x0001):
USBHID(0, 0, vendor_id, product_id, product_release, false) USBHID(0, 0, vendor_id, product_id, product_release, false)
{ {
lock_status = 0; lock_status = 0;
@ -89,7 +89,7 @@ class USBMouseKeyboard: public USBHID, public Stream
this->mouse_type = mouse_type; this->mouse_type = mouse_type;
connect(); connect();
}; };
/** /**
* Write a state of the mouse * Write a state of the mouse
* *
@ -100,8 +100,8 @@ class USBMouseKeyboard: public USBHID, public Stream
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z); bool update(int16_t x, int16_t y, uint8_t buttons, int8_t z);
/** /**
* Move the cursor to (x, y) * Move the cursor to (x, y)
* *
@ -110,7 +110,7 @@ class USBMouseKeyboard: public USBHID, public Stream
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool move(int16_t x, int16_t y); bool move(int16_t x, int16_t y);
/** /**
* Press one or several buttons * Press one or several buttons
* *
@ -118,7 +118,7 @@ class USBMouseKeyboard: public USBHID, public Stream
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool press(uint8_t button); bool press(uint8_t button);
/** /**
* Release one or several buttons * Release one or several buttons
* *
@ -126,22 +126,22 @@ class USBMouseKeyboard: public USBHID, public Stream
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool release(uint8_t button); bool release(uint8_t button);
/** /**
* Double click (MOUSE_LEFT) * Double click (MOUSE_LEFT)
* *
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool doubleClick(); bool doubleClick();
/** /**
* Click * Click
* *
* @param button state of the buttons ( ex: clic(MOUSE_LEFT)) * @param button state of the buttons ( ex: clic(MOUSE_LEFT))
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool click(uint8_t button); bool click(uint8_t button);
/** /**
* Scrolling * Scrolling
* *
@ -151,7 +151,7 @@ class USBMouseKeyboard: public USBHID, public Stream
bool scroll(int8_t z); bool scroll(int8_t z);
/** /**
* To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key
* *
* @code * @code
* //To send CTRL + s (save) * //To send CTRL + s (save)
@ -163,7 +163,7 @@ class USBMouseKeyboard: public USBHID, public Stream
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool keyCode(uint8_t key, uint8_t modifier = 0); bool keyCode(uint8_t key, uint8_t modifier = 0);
/** /**
* Send a character * Send a character
* *
@ -171,7 +171,7 @@ class USBMouseKeyboard: public USBHID, public Stream
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
virtual int _putc(int c); virtual int _putc(int c);
/** /**
* Control media keys * Control media keys
* *
@ -179,7 +179,7 @@ class USBMouseKeyboard: public USBHID, public Stream
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
bool mediaControl(MEDIA_KEY key); bool mediaControl(MEDIA_KEY key);
/** /**
* Read status of lock keys. Useful to switch-on/off leds according to key pressed. Only the first three bits of the result is important: * Read status of lock keys. Useful to switch-on/off leds according to key pressed. Only the first three bits of the result is important:
* - First bit: NUM_LOCK * - First bit: NUM_LOCK
@ -189,30 +189,30 @@ class USBMouseKeyboard: public USBHID, public Stream
* @returns status of lock keys * @returns status of lock keys
*/ */
uint8_t lockStatus(); uint8_t lockStatus();
/* /*
* To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength. * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
* *
* @returns pointer to the report descriptor * @returns pointer to the report descriptor
*/ */
virtual uint8_t * reportDesc(); virtual uint8_t * reportDesc();
/* /*
* Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
* *
* @returns if handle by subclass, return true * @returns if handle by subclass, return true
*/ */
virtual bool EP1_OUT_callback(); virtual bool EP1_OUT_callback();
private: private:
bool mouseWrite(int8_t x, int8_t y, uint8_t buttons, int8_t z); bool mouseWrite(int8_t x, int8_t y, uint8_t buttons, int8_t z);
MOUSE_TYPE mouse_type; MOUSE_TYPE mouse_type;
uint8_t button; uint8_t button;
bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z); bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z);
uint8_t lock_status; uint8_t lock_status;
//dummy otherwise it doesn't compile (we must define all methods of an abstract class) //dummy otherwise it doesn't compile (we must define all methods of an abstract class)
virtual int _getc() { return -1;} virtual int _getc() { return -1;}
}; };

View File

@ -22,7 +22,7 @@
#include "mbed.h" #include "mbed.h"
// MIDI Message Format // MIDI Message Format
// //
// [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ] // [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ]
// //
// MIDI Data Messages (Channel Specific) // MIDI Data Messages (Channel Specific)
@ -43,15 +43,15 @@
class MIDIMessage { class MIDIMessage {
public: public:
MIDIMessage() {} MIDIMessage() {}
MIDIMessage(uint8_t *buf) { MIDIMessage(uint8_t *buf) {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
data[i] = buf[i]; data[i] = buf[i];
} }
// create messages // create messages
/** Create a NoteOff message /** Create a NoteOff message
* @param key Key ID * @param key Key ID
* @param velocity Key velocity (0-127, default = 127) * @param velocity Key velocity (0-127, default = 127)
* @param channel Key channel (0-15, default 0) * @param channel Key channel (0-15, default 0)
@ -62,11 +62,11 @@ public:
msg.data[0] = CABLE_NUM | 0x08; msg.data[0] = CABLE_NUM | 0x08;
msg.data[1] = 0x80 | (channel & 0x0F); msg.data[1] = 0x80 | (channel & 0x0F);
msg.data[2] = key & 0x7F; msg.data[2] = key & 0x7F;
msg.data[3] = velocity & 0x7F; msg.data[3] = velocity & 0x7F;
return msg; return msg;
} }
/** Create a NoteOn message /** Create a NoteOn message
* @param key Key ID * @param key Key ID
* @param velocity Key velocity (0-127, default = 127) * @param velocity Key velocity (0-127, default = 127)
* @param channel Key channel (0-15, default 0) * @param channel Key channel (0-15, default 0)
@ -77,26 +77,26 @@ public:
msg.data[0] = CABLE_NUM | 0x09; msg.data[0] = CABLE_NUM | 0x09;
msg.data[1] = 0x90 | (channel & 0x0F); msg.data[1] = 0x90 | (channel & 0x0F);
msg.data[2] = key & 0x7F; msg.data[2] = key & 0x7F;
msg.data[3] = velocity & 0x7F; msg.data[3] = velocity & 0x7F;
return msg; return msg;
} }
/** Create a PolyPhonic Aftertouch message /** Create a PolyPhonic Aftertouch message
* @param key Key ID * @param key Key ID
* @param pressure Aftertouch pressure (0-127) * @param pressure Aftertouch pressure (0-127)
* @param channel Key channel (0-15, default 0) * @param channel Key channel (0-15, default 0)
* @returns A MIDIMessage * @returns A MIDIMessage
*/ */
static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) { static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) {
MIDIMessage msg; MIDIMessage msg;
msg.data[0] = CABLE_NUM | 0x0A; msg.data[0] = CABLE_NUM | 0x0A;
msg.data[1] = 0xA0 | (channel & 0x0F); msg.data[1] = 0xA0 | (channel & 0x0F);
msg.data[2] = key & 0x7F; msg.data[2] = key & 0x7F;
msg.data[3] = pressure & 0x7F; msg.data[3] = pressure & 0x7F;
return msg; return msg;
} }
/** Create a Control Change message /** Create a Control Change message
* @param control Controller ID * @param control Controller ID
* @param value Controller value (0-127) * @param value Controller value (0-127)
* @param channel Controller channel (0-15, default 0) * @param channel Controller channel (0-15, default 0)
@ -107,63 +107,63 @@ public:
msg.data[0] = CABLE_NUM | 0x0B; msg.data[0] = CABLE_NUM | 0x0B;
msg.data[1] = 0xB0 | (channel & 0x0F); msg.data[1] = 0xB0 | (channel & 0x0F);
msg.data[2] = control & 0x7F; msg.data[2] = control & 0x7F;
msg.data[3] = value & 0x7F; msg.data[3] = value & 0x7F;
return msg; return msg;
} }
/** Create a Program Change message /** Create a Program Change message
* @param program Program ID * @param program Program ID
* @param channel Channel (0-15, default 0) * @param channel Channel (0-15, default 0)
* @returns A MIDIMessage * @returns A MIDIMessage
*/ */
static MIDIMessage ProgramChange(int program, int channel = 0) { static MIDIMessage ProgramChange(int program, int channel = 0) {
MIDIMessage msg; MIDIMessage msg;
msg.data[0] = CABLE_NUM | 0x0C; msg.data[0] = CABLE_NUM | 0x0C;
msg.data[1] = 0xC0 | (channel & 0x0F); msg.data[1] = 0xC0 | (channel & 0x0F);
msg.data[2] = program & 0x7F; msg.data[2] = program & 0x7F;
msg.data[3] = 0x00; msg.data[3] = 0x00;
return msg; return msg;
} }
/** Create a Channel Aftertouch message /** Create a Channel Aftertouch message
* @param pressure Pressure * @param pressure Pressure
* @param channel Key channel (0-15, default 0) * @param channel Key channel (0-15, default 0)
* @returns A MIDIMessage * @returns A MIDIMessage
*/ */
static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) { static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) {
MIDIMessage msg; MIDIMessage msg;
msg.data[0] = CABLE_NUM | 0x0D; msg.data[0] = CABLE_NUM | 0x0D;
msg.data[1] = 0xD0 | (channel & 0x0F); msg.data[1] = 0xD0 | (channel & 0x0F);
msg.data[2] = pressure & 0x7F; msg.data[2] = pressure & 0x7F;
msg.data[3] = 0x00; msg.data[3] = 0x00;
return msg; return msg;
} }
/** Create a Pitch Wheel message /** Create a Pitch Wheel message
* @param pitch Pitch (-8192 - 8191, default = 0) * @param pitch Pitch (-8192 - 8191, default = 0)
* @param channel Channel (0-15, default 0) * @param channel Channel (0-15, default 0)
* @returns A MIDIMessage * @returns A MIDIMessage
*/ */
static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) { static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) {
MIDIMessage msg; MIDIMessage msg;
int p = pitch + 8192; // 0 - 16383, 8192 is center int p = pitch + 8192; // 0 - 16383, 8192 is center
msg.data[0] = CABLE_NUM | 0x0E; msg.data[0] = CABLE_NUM | 0x0E;
msg.data[1] = 0xE0 | (channel & 0x0F); msg.data[1] = 0xE0 | (channel & 0x0F);
msg.data[2] = p & 0x7F; msg.data[2] = p & 0x7F;
msg.data[3] = (p >> 7) & 0x7F; msg.data[3] = (p >> 7) & 0x7F;
return msg; return msg;
} }
/** Create an All Notes Off message /** Create an All Notes Off message
* @param channel Channel (0-15, default 0) * @param channel Channel (0-15, default 0)
* @returns A MIDIMessage * @returns A MIDIMessage
*/ */
static MIDIMessage AllNotesOff(int channel = 0) { static MIDIMessage AllNotesOff(int channel = 0) {
return ControlChange(123, 0, channel); return ControlChange(123, 0, channel);
} }
// decode messages // decode messages
/** MIDI Message Types */ /** MIDI Message Types */
enum MIDIMessageType { enum MIDIMessageType {
ErrorType, ErrorType,
@ -176,16 +176,16 @@ public:
PitchWheelType, PitchWheelType,
AllNotesOffType AllNotesOffType
}; };
/** Read the message type /** Read the message type
* @returns MIDIMessageType * @returns MIDIMessageType
*/ */
MIDIMessageType type() { MIDIMessageType type() {
switch((data[1] >> 4) & 0xF) { switch((data[1] >> 4) & 0xF) {
case 0x8: return NoteOffType; case 0x8: return NoteOffType;
case 0x9: return NoteOnType; case 0x9: return NoteOnType;
case 0xA: return PolyphonicAftertouchType; case 0xA: return PolyphonicAftertouchType;
case 0xB: case 0xB:
if(controller() < 120) { // standard controllers if(controller() < 120) { // standard controllers
return ControlChangeType; return ControlChangeType;
} else if(controller() == 123) { } else if(controller() == 123) {
@ -200,51 +200,51 @@ public:
} }
} }
/** Read the channel number */ /** Read the channel number */
int channel() { int channel() {
return (data[1] & 0x0F); return (data[1] & 0x0F);
} }
/** Read the key ID */ /** Read the key ID */
int key() { int key() {
return (data[2] & 0x7F); return (data[2] & 0x7F);
}
/** Read the velocity */
int velocity() {
return (data[3] & 0x7F);
} }
/** Read the controller value */ /** Read the velocity */
int value() { int velocity() {
return (data[3] & 0x7F); return (data[3] & 0x7F);
} }
/** Read the aftertouch pressure */ /** Read the controller value */
int value() {
return (data[3] & 0x7F);
}
/** Read the aftertouch pressure */
int pressure() { int pressure() {
if(type() == PolyphonicAftertouchType) { if(type() == PolyphonicAftertouchType) {
return (data[3] & 0x7F); return (data[3] & 0x7F);
} else { } else {
return (data[2] & 0x7F); return (data[2] & 0x7F);
} }
} }
/** Read the controller number */ /** Read the controller number */
int controller() { int controller() {
return (data[2] & 0x7F); return (data[2] & 0x7F);
} }
/** Read the program number */ /** Read the program number */
int program() { int program() {
return (data[2] & 0x7F); return (data[2] & 0x7F);
} }
/** Read the pitch value */ /** Read the pitch value */
int pitch() { int pitch() {
int p = ((data[3] & 0x7F) << 7) | (data[2] & 0x7F); int p = ((data[3] & 0x7F) << 7) | (data[2] & 0x7F);
return p - 8192; // 0 - 16383, 8192 is center return p - 8192; // 0 - 16383, 8192 is center
} }
uint8_t data[4]; uint8_t data[4];
}; };

View File

@ -29,7 +29,7 @@
#define DEFAULT_CONFIGURATION (1) #define DEFAULT_CONFIGURATION (1)
/** /**
* USBMIDI example * USBMIDI example
* *
* @code * @code
@ -38,8 +38,8 @@
* *
* USBMIDI midi; * USBMIDI midi;
* *
* int main() { * int main() {
* while (1) { * while (1) {
* for(int i=48; i<83; i++) { // send some messages! * for(int i=48; i<83; i++) { // send some messages!
* midi.write(MIDIMessage::NoteOn(i)); * midi.write(MIDIMessage::NoteOn(i));
* wait(0.25); * wait(0.25);
@ -61,12 +61,12 @@ public:
* @param product_release Your preoduct_release * @param product_release Your preoduct_release
*/ */
USBMIDI(uint16_t vendor_id = 0x0700, uint16_t product_id = 0x0101, uint16_t product_release = 0x0001); USBMIDI(uint16_t vendor_id = 0x0700, uint16_t product_id = 0x0101, uint16_t product_release = 0x0001);
/** /**
* Send a MIDIMessage * Send a MIDIMessage
* *
* @param m The MIDIMessage to send * @param m The MIDIMessage to send
*/ */
void write(MIDIMessage m); void write(MIDIMessage m);
/** /**
@ -75,8 +75,8 @@ public:
* @param fptr function pointer * @param fptr function pointer
*/ */
void attach(void (*fptr)(MIDIMessage)); void attach(void (*fptr)(MIDIMessage));
protected: protected:
virtual bool EP2_OUT_callback(); virtual bool EP2_OUT_callback();
virtual bool USBCallback_setConfiguration(uint8_t configuration); virtual bool USBCallback_setConfiguration(uint8_t configuration);
@ -86,14 +86,14 @@ protected:
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual uint8_t * stringIproductDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual uint8_t * stringIinterfaceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *

View File

@ -79,7 +79,7 @@ public:
* Disconnect the USB MSD device. * Disconnect the USB MSD device.
*/ */
void disconnect(); void disconnect();
/** /**
* Destructor * Destructor
*/ */

View File

@ -73,15 +73,15 @@ void USBCDC::USBCallback_requestCompleted(uint8_t *buf, uint32_t length) {
if (length != 7) { if (length != 7) {
return; return;
} }
CONTROL_TRANSFER * transfer = getTransferPtr(); CONTROL_TRANSFER * transfer = getTransferPtr();
/* Process class-specific requests */ /* Process class-specific requests */
if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
if (transfer->setup.bRequest == CDC_SET_LINE_CODING) { if (transfer->setup.bRequest == CDC_SET_LINE_CODING) {
if (memcmp(cdc_line_coding, buf, 7)) { if (memcmp(cdc_line_coding, buf, 7)) {
memcpy(cdc_line_coding, buf, 7); memcpy(cdc_line_coding, buf, 7);
int baud = buf[0] + (buf[1] << 8) int baud = buf[0] + (buf[1] << 8)
+ (buf[2] << 16) + (buf[3] << 24); + (buf[2] << 16) + (buf[3] << 24);
int stop = buf[4]; int stop = buf[4];
@ -186,7 +186,7 @@ uint8_t * USBCDC::configurationDesc() {
0, // iConfiguration 0, // iConfiguration
0x80, // bmAttributes 0x80, // bmAttributes
50, // bMaxPower 50, // bMaxPower
// IAD to associate the two CDC interfaces // IAD to associate the two CDC interfaces
0x08, // bLength 0x08, // bLength
0x0b, // bDescriptorType 0x0b, // bDescriptorType

View File

@ -40,35 +40,35 @@ public:
USBCDC(uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect_blocking); USBCDC(uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect_blocking);
protected: protected:
/* /*
* Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength. * Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
* *
* @returns pointer to the device descriptor * @returns pointer to the device descriptor
*/ */
virtual uint8_t * deviceDesc(); virtual uint8_t * deviceDesc();
/* /*
* Get string product descriptor * Get string product descriptor
* *
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual uint8_t * stringIproductDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual uint8_t * stringIinterfaceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *
* @returns pointer to the configuration descriptor * @returns pointer to the configuration descriptor
*/ */
virtual uint8_t * configurationDesc(); virtual uint8_t * configurationDesc();
/* /*
* Send a buffer * Send a buffer
* *
@ -78,7 +78,7 @@ protected:
* @returns true if successful * @returns true if successful
*/ */
bool send(uint8_t * buffer, uint32_t size); bool send(uint8_t * buffer, uint32_t size);
/* /*
* Read a buffer from a certain endpoint. Warning: blocking * Read a buffer from a certain endpoint. Warning: blocking
* *
@ -89,7 +89,7 @@ protected:
* @returns true if successful * @returns true if successful
*/ */
bool readEP(uint8_t * buffer, uint32_t * size); bool readEP(uint8_t * buffer, uint32_t * size);
/* /*
* Read a buffer from a certain endpoint. Warning: non blocking * Read a buffer from a certain endpoint. Warning: non blocking
* *
@ -111,7 +111,7 @@ protected:
* @param stop The number of stop bits (1 or 2) * @param stop The number of stop bits (1 or 2)
*/ */
virtual void lineCodingChanged(int baud, int bits, int parity, int stop) {}; virtual void lineCodingChanged(int baud, int bits, int parity, int stop) {};
protected: protected:
virtual bool USBCallback_request(); virtual bool USBCallback_request();
virtual void USBCallback_requestCompleted(uint8_t *buf, uint32_t length); virtual void USBCallback_requestCompleted(uint8_t *buf, uint32_t length);

View File

@ -68,20 +68,20 @@ public:
* @returns true if there is no error, false otherwise * @returns true if there is no error, false otherwise
*/ */
virtual int _putc(int c); virtual int _putc(int c);
/** /**
* Read a character: blocking * Read a character: blocking
* *
* @returns character read * @returns character read
*/ */
virtual int _getc(); virtual int _getc();
/** /**
* Check the number of bytes available. * Check the number of bytes available.
* *
* @returns the number of bytes available * @returns the number of bytes available
*/ */
uint8_t available(); uint8_t available();
/** Determine if there is a character available to read /** Determine if there is a character available to read
* *
@ -90,7 +90,7 @@ public:
* 0 otherwise * 0 otherwise
*/ */
int readable() { return available() ? 1 : 0; } int readable() { return available() ? 1 : 0; }
/** Determine if there is space available to write a character /** Determine if there is space available to write a character
* *
* @returns * @returns
@ -98,9 +98,9 @@ public:
* 0 otherwise * 0 otherwise
*/ */
int writeable() { return 1; } // always return 1, for write operation is blocking int writeable() { return 1; } // always return 1, for write operation is blocking
/** /**
* Write a block of data. * Write a block of data.
* *
* For more efficiency, a block of size 64 (maximum size of a bulk endpoint) has to be written. * For more efficiency, a block of size 64 (maximum size of a bulk endpoint) has to be written.
* *
@ -112,7 +112,7 @@ public:
bool writeBlock(uint8_t * buf, uint16_t size); bool writeBlock(uint8_t * buf, uint16_t size);
/** /**
* Attach a member function to call when a packet is received. * Attach a member function to call when a packet is received.
* *
* @param tptr pointer to the object to call the member function on * @param tptr pointer to the object to call the member function on
* @param mptr pointer to the member function to be called * @param mptr pointer to the member function to be called

View File

@ -50,10 +50,10 @@ void USBDeviceConnected::init() {
INTERFACE * USBDeviceConnected::getInterface(uint8_t index) { INTERFACE * USBDeviceConnected::getInterface(uint8_t index) {
if (index >= MAX_INTF) if (index >= MAX_INTF)
return NULL; return NULL;
if (intf[index].in_use) if (intf[index].in_use)
return &intf[index]; return &intf[index];
return NULL; return NULL;
} }

View File

@ -33,7 +33,7 @@ typedef struct {
USBEndpoint * ep[MAX_ENDPOINT_PER_INTERFACE]; USBEndpoint * ep[MAX_ENDPOINT_PER_INTERFACE];
FunctionPointer detach; FunctionPointer detach;
char name[10]; char name[10];
} INTERFACE; } INTERFACE;
/** /**
* USBDeviceConnected class * USBDeviceConnected class
@ -157,7 +157,7 @@ public:
inline USBHostHub * getHubParent() { return hub_parent; }; inline USBHostHub * getHubParent() { return hub_parent; };
inline uint8_t getNbIntf() { return nb_interf; }; inline uint8_t getNbIntf() { return nb_interf; };
inline const char * getName(uint8_t intf_nb) { return intf[intf_nb].name; }; inline const char * getName(uint8_t intf_nb) { return intf[intf_nb].name; };
// in case this device is a hub // in case this device is a hub
USBHostHub * hub; USBHostHub * hub;

View File

@ -29,7 +29,7 @@ void USBEndpoint::init(HCED * hced_, ENDPOINT_TYPE type_, ENDPOINT_DIRECTION dir
memcpy((HCTD**)td_list, td_list_, sizeof(HCTD*)*2); //TODO: Maybe should add a param for td_list size... at least a define memcpy((HCTD**)td_list, td_list_, sizeof(HCTD*)*2); //TODO: Maybe should add a param for td_list size... at least a define
memset(td_list_[0], 0, sizeof(HCTD)); memset(td_list_[0], 0, sizeof(HCTD));
memset(td_list_[1], 0, sizeof(HCTD)); memset(td_list_[1], 0, sizeof(HCTD));
td_list[0]->ep = this; td_list[0]->ep = this;
td_list[1]->ep = this; td_list[1]->ep = this;
@ -52,7 +52,7 @@ void USBEndpoint::init(HCED * hced_, ENDPOINT_TYPE type_, ENDPOINT_DIRECTION dir
td_current = td_list[0]; td_current = td_list[0];
td_next = td_list[1]; td_next = td_list[1];
intf_nb = 0; intf_nb = 0;
state = USB_TYPE_IDLE; state = USB_TYPE_IDLE;

View File

@ -136,9 +136,9 @@ public:
inline bool isSetup() { return setup; } inline bool isSetup() { return setup; }
inline USBEndpoint * nextEndpoint() { return (USBEndpoint*)nextEp; }; inline USBEndpoint * nextEndpoint() { return (USBEndpoint*)nextEp; };
inline uint8_t getIntfNb() { return intf_nb; }; inline uint8_t getIntfNb() { return intf_nb; };
USBDeviceConnected * dev; USBDeviceConnected * dev;
Queue<uint8_t, 1> ep_queue; Queue<uint8_t, 1> ep_queue;
private: private:
@ -163,7 +163,7 @@ private:
volatile HCTD * td_list[2]; volatile HCTD * td_list[2];
volatile HCTD * td_current; volatile HCTD * td_current;
volatile HCTD * td_next; volatile HCTD * td_next;
uint8_t intf_nb; uint8_t intf_nb;
}; };

View File

@ -57,7 +57,7 @@ USBHALHost::USBHALHost() {
void USBHALHost::init() { void USBHALHost::init() {
NVIC_DisableIRQ(USB_IRQn); NVIC_DisableIRQ(USB_IRQn);
//Cut power //Cut power
LPC_SC->PCONP &= ~(1UL<<31); LPC_SC->PCONP &= ~(1UL<<31);
wait_ms(100); wait_ms(100);
@ -98,7 +98,7 @@ void USBHALHost::init() {
// software reset // software reset
LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR; LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
// Write Fm Interval and Largest Data Packet Counter // Write Fm Interval and Largest Data Packet Counter
LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL;
LPC_USB->HcPeriodicStart = FI * 90 / 100; LPC_USB->HcPeriodicStart = FI * 90 / 100;
@ -109,7 +109,7 @@ void USBHALHost::init() {
LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;
LPC_USB->HcHCCA = (uint32_t)(usb_hcca); LPC_USB->HcHCCA = (uint32_t)(usb_hcca);
// Clear Interrrupt Status // Clear Interrrupt Status
LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
@ -249,9 +249,9 @@ void USBHALHost::freeTD(volatile uint8_t * td) {
void USBHALHost::resetRootHub() { void USBHALHost::resetRootHub() {
// Initiate port reset // Initiate port reset
LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS;
while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS); while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS);
// ...and clear port reset signal // ...and clear port reset signal
LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
} }
@ -266,11 +266,11 @@ void USBHALHost::_usbisr(void) {
void USBHALHost::UsbIrqhandler() { void USBHALHost::UsbIrqhandler() {
if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process? if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process?
{ {
uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable; uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable;
// Root hub status change interrupt // Root hub status change interrupt
if (int_status & OR_INTR_STATUS_RHSC) { if (int_status & OR_INTR_STATUS_RHSC) {
if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC) { if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC) {
if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) { if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) {
// When DRWE is on, Connect Status Change // When DRWE is on, Connect Status Change
@ -278,27 +278,27 @@ void USBHALHost::UsbIrqhandler() {
} else { } else {
//Root device connected //Root device connected
if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) { if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) {
// wait 150ms to avoid bounce // wait 150ms to avoid bounce
wait_ms(150); wait_ms(150);
//Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA); deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA);
} }
//Root device disconnected //Root device disconnected
else { else {
if (!(int_status & OR_INTR_STATUS_WDH)) { if (!(int_status & OR_INTR_STATUS_WDH)) {
usb_hcca->DoneHead = 0; usb_hcca->DoneHead = 0;
} }
// wait 200ms to avoid bounce // wait 200ms to avoid bounce
wait_ms(200); wait_ms(200);
deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE); deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE);
if (int_status & OR_INTR_STATUS_WDH) { if (int_status & OR_INTR_STATUS_WDH) {
usb_hcca->DoneHead = 0; usb_hcca->DoneHead = 0;
LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH; LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;

View File

@ -33,61 +33,61 @@ protected:
* init variables and memory where will be stored HCCA, ED and TD * init variables and memory where will be stored HCCA, ED and TD
*/ */
USBHALHost(); USBHALHost();
/** /**
* Initialize host controller. Enable USB interrupts. This part is not in the constructor because, * Initialize host controller. Enable USB interrupts. This part is not in the constructor because,
* this function calls a virtual method if a device is already connected * this function calls a virtual method if a device is already connected
*/ */
void init(); void init();
/** /**
* reset the root hub * reset the root hub
*/ */
void resetRootHub(); void resetRootHub();
/** /**
* return the value contained in the control HEAD ED register * return the value contained in the control HEAD ED register
* *
* @returns address of the control Head ED * @returns address of the control Head ED
*/ */
uint32_t controlHeadED(); uint32_t controlHeadED();
/** /**
* return the value contained in the bulk HEAD ED register * return the value contained in the bulk HEAD ED register
* *
* @returns address of the bulk head ED * @returns address of the bulk head ED
*/ */
uint32_t bulkHeadED(); uint32_t bulkHeadED();
/** /**
* return the value of the head interrupt ED contained in the HCCA * return the value of the head interrupt ED contained in the HCCA
* *
* @returns address of the head interrupt ED contained in the HCCA * @returns address of the head interrupt ED contained in the HCCA
*/ */
uint32_t interruptHeadED(); uint32_t interruptHeadED();
/** /**
* Update the head ED for control transfers * Update the head ED for control transfers
*/ */
void updateControlHeadED(uint32_t addr); void updateControlHeadED(uint32_t addr);
/** /**
* Update the head ED for bulk transfers * Update the head ED for bulk transfers
*/ */
void updateBulkHeadED(uint32_t addr); void updateBulkHeadED(uint32_t addr);
/** /**
* Update the head ED for interrupt transfers * Update the head ED for interrupt transfers
*/ */
void updateInterruptHeadED(uint32_t addr); void updateInterruptHeadED(uint32_t addr);
/** /**
* Enable List for the specified endpoint type * Enable List for the specified endpoint type
* *
* @param type enable the list of ENDPOINT_TYPE type * @param type enable the list of ENDPOINT_TYPE type
*/ */
void enableList(ENDPOINT_TYPE type); void enableList(ENDPOINT_TYPE type);
/** /**
* Disable List for the specified endpoint type * Disable List for the specified endpoint type
* *
@ -104,7 +104,7 @@ protected:
* @param hub_parent reference to the hub where the device is connected (NULL if the hub parent is the root hub) * @param hub_parent reference to the hub where the device is connected (NULL if the hub parent is the root hub)
*/ */
virtual void deviceConnected(int hub, int port, bool lowSpeed, USBHostHub * hub_parent = NULL) = 0; virtual void deviceConnected(int hub, int port, bool lowSpeed, USBHostHub * hub_parent = NULL) = 0;
/** /**
* Virtual method called when a device has been disconnected * Virtual method called when a device has been disconnected
* *
@ -114,35 +114,35 @@ protected:
* @param addr list of the TDs which have been completed to dequeue freed TDs * @param addr list of the TDs which have been completed to dequeue freed TDs
*/ */
virtual void deviceDisconnected(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr) = 0; virtual void deviceDisconnected(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr) = 0;
/** /**
* Virtual method called when a transfer has been completed * Virtual method called when a transfer has been completed
* *
* @param addr list of the TDs which have been completed * @param addr list of the TDs which have been completed
*/ */
virtual void transferCompleted(volatile uint32_t addr) = 0; virtual void transferCompleted(volatile uint32_t addr) = 0;
/** /**
* Find a memory section for a new ED * Find a memory section for a new ED
* *
* @returns the address of the new ED * @returns the address of the new ED
*/ */
volatile uint8_t * getED(); volatile uint8_t * getED();
/** /**
* Find a memory section for a new TD * Find a memory section for a new TD
* *
* @returns the address of the new TD * @returns the address of the new TD
*/ */
volatile uint8_t * getTD(); volatile uint8_t * getTD();
/** /**
* Release a previous memory section reserved for an ED * Release a previous memory section reserved for an ED
* *
* @param ed address of the ED * @param ed address of the ED
*/ */
void freeED(volatile uint8_t * ed); void freeED(volatile uint8_t * ed);
/** /**
* Release a previous memory section reserved for an TD * Release a previous memory section reserved for an TD
* *
@ -161,7 +161,7 @@ private:
uint8_t volatile * usb_tdBuf; //4 bytes aligned uint8_t volatile * usb_tdBuf; //4 bytes aligned
static USBHALHost * instHost; static USBHALHost * instHost;
bool volatile edBufAlloc[MAX_ENDPOINT]; bool volatile edBufAlloc[MAX_ENDPOINT];
bool volatile tdBufAlloc[MAX_TD]; bool volatile tdBufAlloc[MAX_TD];
}; };

View File

@ -47,7 +47,7 @@ USBHost * USBHost::instHost = NULL;
* - call the callback attached to the endpoint where the td is attached * - call the callback attached to the endpoint where the td is attached
*/ */
void USBHost::usb_process() { void USBHost::usb_process() {
bool controlListState; bool controlListState;
bool bulkListState; bool bulkListState;
bool interruptListState; bool interruptListState;
@ -60,29 +60,29 @@ void USBHost::usb_process() {
#if DEBUG_TRANSFER #if DEBUG_TRANSFER
uint8_t * buf_transfer; uint8_t * buf_transfer;
#endif #endif
#if MAX_HUB_NB #if MAX_HUB_NB
uint8_t k; uint8_t k;
#endif #endif
while(1) { while(1) {
osEvent evt = mail_usb_event.get(); osEvent evt = mail_usb_event.get();
if (evt.status == osEventMail) { if (evt.status == osEventMail) {
message_t * usb_msg = (message_t*)evt.value.p; message_t * usb_msg = (message_t*)evt.value.p;
switch (usb_msg->event_id) { switch (usb_msg->event_id) {
// a new device has been connected // a new device has been connected
case DEVICE_CONNECTED_EVENT: case DEVICE_CONNECTED_EVENT:
too_many_hub = false; too_many_hub = false;
buf[4] = 0; buf[4] = 0;
do do
{ {
Lock lock(this); Lock lock(this);
for (i = 0; i < MAX_DEVICE_CONNECTED; i++) { for (i = 0; i < MAX_DEVICE_CONNECTED; i++) {
if (!deviceInUse[i]) { if (!deviceInUse[i]) {
USB_DBG_EVENT("new device connected: %p\r\n", &devices[i]); USB_DBG_EVENT("new device connected: %p\r\n", &devices[i]);
@ -92,68 +92,68 @@ void USBHost::usb_process() {
break; break;
} }
} }
if (i == MAX_DEVICE_CONNECTED) { if (i == MAX_DEVICE_CONNECTED) {
USB_ERR("Too many device connected!!\r\n"); USB_ERR("Too many device connected!!\r\n");
continue; continue;
} }
if (!controlEndpointAllocated) { if (!controlEndpointAllocated) {
control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00); control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00);
addEndpoint(NULL, 0, (USBEndpoint*)control); addEndpoint(NULL, 0, (USBEndpoint*)control);
controlEndpointAllocated = true; controlEndpointAllocated = true;
} }
#if MAX_HUB_NB #if MAX_HUB_NB
if (usb_msg->hub_parent) if (usb_msg->hub_parent)
devices[i].setHubParent((USBHostHub *)(usb_msg->hub_parent)); devices[i].setHubParent((USBHostHub *)(usb_msg->hub_parent));
#endif #endif
for (j = 0; j < timeout_set_addr; j++) { for (j = 0; j < timeout_set_addr; j++) {
resetDevice(&devices[i]); resetDevice(&devices[i]);
// set size of control endpoint // set size of control endpoint
devices[i].setSizeControlEndpoint(8); devices[i].setSizeControlEndpoint(8);
devices[i].activeAddress(false); devices[i].activeAddress(false);
// get first 8 bit of device descriptor // get first 8 bit of device descriptor
// and check if we deal with a hub // and check if we deal with a hub
USB_DBG("usb_thread read device descriptor on dev: %p\r\n", &devices[i]); USB_DBG("usb_thread read device descriptor on dev: %p\r\n", &devices[i]);
res = getDeviceDescriptor(&devices[i], buf, 8); res = getDeviceDescriptor(&devices[i], buf, 8);
if (res != USB_TYPE_OK) { if (res != USB_TYPE_OK) {
USB_ERR("usb_thread could not read dev descr"); USB_ERR("usb_thread could not read dev descr");
continue; continue;
} }
// set size of control endpoint // set size of control endpoint
devices[i].setSizeControlEndpoint(buf[7]); devices[i].setSizeControlEndpoint(buf[7]);
// second step: set an address to the device // second step: set an address to the device
res = setAddress(&devices[i], devices[i].getAddress()); res = setAddress(&devices[i], devices[i].getAddress());
if (res != USB_TYPE_OK) { if (res != USB_TYPE_OK) {
USB_ERR("SET ADDR FAILED"); USB_ERR("SET ADDR FAILED");
continue; continue;
} }
devices[i].activeAddress(true); devices[i].activeAddress(true);
USB_DBG("Address of %p: %d", &devices[i], devices[i].getAddress()); USB_DBG("Address of %p: %d", &devices[i], devices[i].getAddress());
// try to read again the device descriptor to check if the device // try to read again the device descriptor to check if the device
// answers to its new address // answers to its new address
res = getDeviceDescriptor(&devices[i], buf, 8); res = getDeviceDescriptor(&devices[i], buf, 8);
if (res == USB_TYPE_OK) { if (res == USB_TYPE_OK) {
break; break;
} }
Thread::wait(100); Thread::wait(100);
} }
USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices[i], usb_msg->hub, usb_msg->port); USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices[i], usb_msg->hub, usb_msg->port);
#if MAX_HUB_NB #if MAX_HUB_NB
if (buf[4] == HUB_CLASS) { if (buf[4] == HUB_CLASS) {
for (k = 0; k < MAX_HUB_NB; k++) { for (k = 0; k < MAX_HUB_NB; k++) {
@ -169,49 +169,49 @@ void USBHost::usb_process() {
break; break;
} }
} }
if (k == MAX_HUB_NB) { if (k == MAX_HUB_NB) {
USB_ERR("Too many hubs connected!!\r\n"); USB_ERR("Too many hubs connected!!\r\n");
too_many_hub = true; too_many_hub = true;
} }
} }
if (usb_msg->hub_parent) if (usb_msg->hub_parent)
((USBHostHub *)(usb_msg->hub_parent))->deviceConnected(&devices[i]); ((USBHostHub *)(usb_msg->hub_parent))->deviceConnected(&devices[i]);
#endif #endif
if ((i < MAX_DEVICE_CONNECTED) && !too_many_hub) { if ((i < MAX_DEVICE_CONNECTED) && !too_many_hub) {
deviceInUse[i] = true; deviceInUse[i] = true;
} }
} while(0); } while(0);
break; break;
// a device has been disconnected // a device has been disconnected
case DEVICE_DISCONNECTED_EVENT: case DEVICE_DISCONNECTED_EVENT:
do do
{ {
Lock lock(this); Lock lock(this);
controlListState = disableList(CONTROL_ENDPOINT); controlListState = disableList(CONTROL_ENDPOINT);
bulkListState = disableList(BULK_ENDPOINT); bulkListState = disableList(BULK_ENDPOINT);
interruptListState = disableList(INTERRUPT_ENDPOINT); interruptListState = disableList(INTERRUPT_ENDPOINT);
idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent)); idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent));
if (idx != -1) { if (idx != -1) {
freeDevice((USBDeviceConnected*)&devices[idx]); freeDevice((USBDeviceConnected*)&devices[idx]);
} }
if (controlListState) enableList(CONTROL_ENDPOINT); if (controlListState) enableList(CONTROL_ENDPOINT);
if (bulkListState) enableList(BULK_ENDPOINT); if (bulkListState) enableList(BULK_ENDPOINT);
if (interruptListState) enableList(INTERRUPT_ENDPOINT); if (interruptListState) enableList(INTERRUPT_ENDPOINT);
} while(0); } while(0);
break; break;
// a td has been processed // a td has been processed
// call callback on the ed associated to the td // call callback on the ed associated to the td
// we are not in ISR -> users can use printf in their callback method // we are not in ISR -> users can use printf in their callback method
@ -241,7 +241,7 @@ void USBHost::usb_process() {
} }
break; break;
} }
mail_usb_event.free(usb_msg); mail_usb_event.free(usb_msg);
} }
} }
@ -272,7 +272,7 @@ USBHost::USBHost() : usbThread(USBHost::usb_process_static, (void *)this, osPrio
for (uint8_t j = 0; j < MAX_INTF; j++) for (uint8_t j = 0; j < MAX_INTF; j++)
deviceAttachedDriver[i][j] = false; deviceAttachedDriver[i][j] = false;
} }
#if MAX_HUB_NB #if MAX_HUB_NB
for (uint8_t i = 0; i < MAX_HUB_NB; i++) { for (uint8_t i = 0; i < MAX_HUB_NB; i++) {
hubs[i].setHost(this); hubs[i].setHost(this);
@ -313,7 +313,7 @@ void USBHost::transferCompleted(volatile uint32_t addr)
tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below
if (td->ep != NULL) { if (td->ep != NULL) {
USBEndpoint * ep = (USBEndpoint *)(td->ep); USBEndpoint * ep = (USBEndpoint *)(td->ep);
if (((HCTD *)td)->control >> 28) { if (((HCTD *)td)->control >> 28) {
state = ((HCTD *)td)->control >> 28; state = ((HCTD *)td)->control >> 28;
} else { } else {
@ -321,9 +321,9 @@ void USBHost::transferCompleted(volatile uint32_t addr)
ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart()); ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart());
state = 16 /*USB_TYPE_IDLE*/; state = 16 /*USB_TYPE_IDLE*/;
} }
ep->unqueueTransfer(td); ep->unqueueTransfer(td);
if (ep->getType() != CONTROL_ENDPOINT) { if (ep->getType() != CONTROL_ENDPOINT) {
// callback on the processed td will be called from the usb_thread (not in ISR) // callback on the processed td will be called from the usb_thread (not in ISR)
message_t * usb_msg = mail_usb_event.alloc(); message_t * usb_msg = mail_usb_event.alloc();
@ -360,7 +360,7 @@ USBHost * USBHost::getHostInst()
if (deviceInited[idx]) if (deviceInited[idx])
return; return;
} }
message_t * usb_msg = mail_usb_event.alloc(); message_t * usb_msg = mail_usb_event.alloc();
usb_msg->event_id = DEVICE_CONNECTED_EVENT; usb_msg->event_id = DEVICE_CONNECTED_EVENT;
usb_msg->hub = hub; usb_msg->hub = hub;
@ -384,7 +384,7 @@ USBHost * USBHost::getHostInst()
} else { } else {
return; return;
} }
message_t * usb_msg = mail_usb_event.alloc(); message_t * usb_msg = mail_usb_event.alloc();
usb_msg->event_id = DEVICE_DISCONNECTED_EVENT; usb_msg->event_id = DEVICE_DISCONNECTED_EVENT;
usb_msg->hub = hub; usb_msg->hub = hub;
@ -397,7 +397,7 @@ void USBHost::freeDevice(USBDeviceConnected * dev)
{ {
USBEndpoint * ep = NULL; USBEndpoint * ep = NULL;
HCED * ed = NULL; HCED * ed = NULL;
#if MAX_HUB_NB #if MAX_HUB_NB
if (dev->getClass() == HUB_CLASS) { if (dev->getClass() == HUB_CLASS) {
if (dev->hub == NULL) { if (dev->hub == NULL) {
@ -412,13 +412,13 @@ void USBHost::freeDevice(USBDeviceConnected * dev)
} }
} }
} }
// notify hub parent that this device has been disconnected // notify hub parent that this device has been disconnected
if (dev->getHubParent()) if (dev->getHubParent())
dev->getHubParent()->deviceDisconnected(dev); dev->getHubParent()->deviceDisconnected(dev);
#endif #endif
int idx = findDevice(dev); int idx = findDevice(dev);
if (idx != -1) { if (idx != -1) {
deviceInUse[idx] = false; deviceInUse[idx] = false;
@ -481,7 +481,7 @@ void USBHost::unqueueEndpoint(USBEndpoint * ep)
updateInterruptHeadED(0); updateInterruptHeadED(0);
headInterruptEndpoint = current->nextEndpoint(); headInterruptEndpoint = current->nextEndpoint();
} }
// modify tail // modify tail
switch (current->getType()) { switch (current->getType()) {
case BULK_ENDPOINT: case BULK_ENDPOINT:
@ -553,7 +553,7 @@ USB_TYPE USBHost::resetDevice(USBDeviceConnected * dev)
deviceReset[index] = true; deviceReset[index] = true;
return USB_TYPE_OK; return USB_TYPE_OK;
} }
return USB_TYPE_ERROR; return USB_TYPE_ERROR;
} }
@ -577,7 +577,7 @@ bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint
if ((dev != NULL) && dev->getSpeed()) { if ((dev != NULL) && dev->getSpeed()) {
ep->setSpeed(dev->getSpeed()); ep->setSpeed(dev->getSpeed());
} }
ep->setIntfNb(intf_nb); ep->setIntfNb(intf_nb);
// queue the new USBEndpoint on the ED list // queue the new USBEndpoint on the ED list
@ -626,7 +626,7 @@ bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint
default: default:
return false; return false;
} }
ep->dev = dev; ep->dev = dev;
dev->addEndpoint(intf_nb, ep); dev->addEndpoint(intf_nb, ep);
@ -733,7 +733,7 @@ USB_TYPE USBHost::addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len)
ed->queueTransfer(); ed->queueTransfer();
printList(type); printList(type);
enableList(type); enableList(type);
td_mutex.unlock(); td_mutex.unlock();
return USB_TYPE_PROCESSING; return USB_TYPE_PROCESSING;
@ -750,7 +750,7 @@ USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf, u
0, buf, MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf)); 0, buf, MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf));
if (len_dev_descr) if (len_dev_descr)
*len_dev_descr = MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf); *len_dev_descr = MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf);
return t; return t;
} }
@ -772,10 +772,10 @@ USB_TYPE USBHost::getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t *
} }
total_conf_descr_length = buf[2] | (buf[3] << 8); total_conf_descr_length = buf[2] | (buf[3] << 8);
total_conf_descr_length = MIN(max_len_buf, total_conf_descr_length); total_conf_descr_length = MIN(max_len_buf, total_conf_descr_length);
if (len_conf_descr) if (len_conf_descr)
*len_conf_descr = total_conf_descr_length; *len_conf_descr = total_conf_descr_length;
USB_DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]); USB_DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]);
return controlRead( dev, return controlRead( dev,
@ -792,7 +792,7 @@ USB_TYPE USBHost::setAddress(USBDeviceConnected * dev, uint8_t address) {
SET_ADDRESS, SET_ADDRESS,
address, address,
0, NULL, 0); 0, NULL, 0);
} }
USB_TYPE USBHost::setConfiguration(USBDeviceConnected * dev, uint8_t conf) USB_TYPE USBHost::setConfiguration(USBDeviceConnected * dev, uint8_t conf)
@ -821,18 +821,18 @@ USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerato
{ {
uint16_t total_conf_descr_length = 0; uint16_t total_conf_descr_length = 0;
USB_TYPE res; USB_TYPE res;
do do
{ {
Lock lock(this); Lock lock(this);
// don't enumerate a device which all interfaces are registered to a specific driver // don't enumerate a device which all interfaces are registered to a specific driver
int index = findDevice(dev); int index = findDevice(dev);
if (index == -1) { if (index == -1) {
return USB_TYPE_ERROR; return USB_TYPE_ERROR;
} }
uint8_t nb_intf_attached = numberDriverAttached(dev); uint8_t nb_intf_attached = numberDriverAttached(dev);
USB_DBG("dev: %p nb_intf: %d", dev, dev->getNbIntf()); USB_DBG("dev: %p nb_intf: %d", dev, dev->getNbIntf());
USB_DBG("dev: %p nb_intf_attached: %d", dev, nb_intf_attached); USB_DBG("dev: %p nb_intf_attached: %d", dev, nb_intf_attached);
@ -840,9 +840,9 @@ USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerato
USB_DBG("Don't enumerate dev: %p because all intf are registered with a driver", dev); USB_DBG("Don't enumerate dev: %p because all intf are registered with a driver", dev);
return USB_TYPE_OK; return USB_TYPE_OK;
} }
USB_DBG("Enumerate dev: %p", dev); USB_DBG("Enumerate dev: %p", dev);
// third step: get the whole device descriptor to see vid, pid // third step: get the whole device descriptor to see vid, pid
res = getDeviceDescriptor(dev, data, DEVICE_DESCRIPTOR_LENGTH); res = getDeviceDescriptor(dev, data, DEVICE_DESCRIPTOR_LENGTH);
@ -850,7 +850,7 @@ USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerato
USB_DBG("GET DEV DESCR FAILED"); USB_DBG("GET DEV DESCR FAILED");
return res; return res;
} }
dev->setClass(data[4]); dev->setClass(data[4]);
dev->setSubClass(data[5]); dev->setSubClass(data[5]);
dev->setProtocol(data[6]); dev->setProtocol(data[6]);
@ -877,7 +877,7 @@ USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerato
// only set configuration if not enumerated before // only set configuration if not enumerated before
if (!dev->isEnumerated()) { if (!dev->isEnumerated()) {
USB_DBG("Set configuration 1 on dev: %p", dev); USB_DBG("Set configuration 1 on dev: %p", dev);
// sixth step: set configuration (only 1 supported) // sixth step: set configuration (only 1 supported)
res = setConfiguration(dev, 1); res = setConfiguration(dev, 1);
@ -887,12 +887,12 @@ USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerato
return res; return res;
} }
} }
dev->setEnumerated(); dev->setEnumerated();
// Now the device is enumerated! // Now the device is enumerated!
USB_DBG("dev %p is enumerated\r\n", dev); USB_DBG("dev %p is enumerated\r\n", dev);
} while(0); } while(0);
// Some devices may require this delay // Some devices may require this delay
@ -991,17 +991,17 @@ USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint
} }
USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking, ENDPOINT_TYPE type, bool write) { USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking, ENDPOINT_TYPE type, bool write) {
#if DEBUG_TRANSFER #if DEBUG_TRANSFER
const char * type_str = (type == BULK_ENDPOINT) ? "BULK" : ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" : "ISOCHRONOUS"); const char * type_str = (type == BULK_ENDPOINT) ? "BULK" : ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" : "ISOCHRONOUS");
USB_DBG_TRANSFER("----- %s %s [dev: %p - %s - hub: %d - port: %d - addr: %d - ep: %02X]------", type_str, (write) ? "WRITE" : "READ", dev, dev->getName(ep->getIntfNb()), dev->getHub(), dev->getPort(), dev->getAddress(), ep->getAddress()); USB_DBG_TRANSFER("----- %s %s [dev: %p - %s - hub: %d - port: %d - addr: %d - ep: %02X]------", type_str, (write) ? "WRITE" : "READ", dev, dev->getName(ep->getIntfNb()), dev->getHub(), dev->getPort(), dev->getAddress(), ep->getAddress());
#endif #endif
Lock lock(this); Lock lock(this);
USB_TYPE res; USB_TYPE res;
ENDPOINT_DIRECTION dir = (write) ? OUT : IN; ENDPOINT_DIRECTION dir = (write) ? OUT : IN;
if (dev == NULL) { if (dev == NULL) {
USB_ERR("dev NULL"); USB_ERR("dev NULL");
return USB_TYPE_ERROR; return USB_TYPE_ERROR;
@ -1026,7 +1026,7 @@ USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, ui
USB_ERR("[ep: %p - dev: %p] USBEndpoint addr and device addr don't match", ep, ep->dev); USB_ERR("[ep: %p - dev: %p] USBEndpoint addr and device addr don't match", ep, ep->dev);
return USB_TYPE_ERROR; return USB_TYPE_ERROR;
} }
#if DEBUG_TRANSFER #if DEBUG_TRANSFER
if (write) { if (write) {
USB_DBG_TRANSFER("%s WRITE buffer", type_str); USB_DBG_TRANSFER("%s WRITE buffer", type_str);
@ -1038,19 +1038,19 @@ USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, ui
addTransfer(ep, buf, len); addTransfer(ep, buf, len);
if (blocking) { if (blocking) {
ep->ep_queue.get(); ep->ep_queue.get();
res = ep->getState(); res = ep->getState();
USB_DBG_TRANSFER("%s TRANSFER res: %s on ep: %p\r\n", type_str, ep->getStateString(), ep); USB_DBG_TRANSFER("%s TRANSFER res: %s on ep: %p\r\n", type_str, ep->getStateString(), ep);
if (res != USB_TYPE_IDLE) { if (res != USB_TYPE_IDLE) {
return res; return res;
} }
return USB_TYPE_OK; return USB_TYPE_OK;
} }
return USB_TYPE_PROCESSING; return USB_TYPE_PROCESSING;
} }

View File

@ -35,7 +35,7 @@ public:
* Static method to create or retrieve the single USBHost instance * Static method to create or retrieve the single USBHost instance
*/ */
static USBHost * getHostInst(); static USBHost * getHostInst();
/** /**
* Control read: setup stage, data stage and status stage * Control read: setup stage, data stage and status stage
* *
@ -186,19 +186,19 @@ public:
dev->onDisconnect(intf, fn); dev->onDisconnect(intf, fn);
} }
} }
/** /**
* Instantiate to protect USB thread from accessing shared objects (USBConnectedDevices and Interfaces) * Instantiate to protect USB thread from accessing shared objects (USBConnectedDevices and Interfaces)
*/ */
class Lock class Lock
{ {
public: public:
Lock(USBHost* pHost); Lock(USBHost* pHost);
~Lock(); ~Lock();
private: private:
USBHost* m_pHost; USBHost* m_pHost;
}; };
friend class USBHostHub; friend class USBHostHub;
protected: protected:
@ -257,7 +257,7 @@ private:
bool deviceAttachedDriver[MAX_DEVICE_CONNECTED][MAX_INTF]; bool deviceAttachedDriver[MAX_DEVICE_CONNECTED][MAX_INTF];
bool deviceReset[MAX_DEVICE_CONNECTED]; bool deviceReset[MAX_DEVICE_CONNECTED];
bool deviceInited[MAX_DEVICE_CONNECTED]; bool deviceInited[MAX_DEVICE_CONNECTED];
#if MAX_HUB_NB #if MAX_HUB_NB
USBHostHub hubs[MAX_HUB_NB]; USBHostHub hubs[MAX_HUB_NB];
bool hub_in_use[MAX_HUB_NB]; bool hub_in_use[MAX_HUB_NB];
@ -265,7 +265,7 @@ private:
// to store a setup packet // to store a setup packet
uint8_t setupPacket[8]; uint8_t setupPacket[8];
typedef struct { typedef struct {
uint8_t event_id; uint8_t event_id;
void * td_addr; void * td_addr;
@ -275,17 +275,17 @@ private:
uint8_t td_state; uint8_t td_state;
void * hub_parent; void * hub_parent;
} message_t; } message_t;
Thread usbThread; Thread usbThread;
void usb_process(); void usb_process();
static void usb_process_static(void const * arg); static void usb_process_static(void const * arg);
Mail<message_t, 10> mail_usb_event; Mail<message_t, 10> mail_usb_event;
Mutex usb_mutex; Mutex usb_mutex;
Mutex td_mutex; Mutex td_mutex;
// buffer for conf descriptor // buffer for conf descriptor
uint8_t data[415]; uint8_t data[415];
/** /**
* Add a transfer on the TD linked list associated to an ED * Add a transfer on the TD linked list associated to an ED
* *
@ -296,7 +296,7 @@ private:
* @return status of the transfer * @return status of the transfer
*/ */
USB_TYPE addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len) ; USB_TYPE addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len) ;
/** /**
* Link the USBEndpoint to the linked list and attach an USBEndpoint this USBEndpoint to a device * Link the USBEndpoint to the linked list and attach an USBEndpoint this USBEndpoint to a device
* *
@ -318,7 +318,7 @@ private:
* @returns pointer on the USBEndpoint created * @returns pointer on the USBEndpoint created
*/ */
USBEndpoint * newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr) ; USBEndpoint * newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr) ;
/** /**
* Request the device descriptor * Request the device descriptor
* *
@ -338,7 +338,7 @@ private:
* @param len_conf_descr pointer to store the length of the packet transferred * @param len_conf_descr pointer to store the length of the packet transferred
*/ */
USB_TYPE getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_conf_descr = NULL); USB_TYPE getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_conf_descr = NULL);
/** /**
* Set the address of a specific device * Set the address of a specific device
* *
@ -354,7 +354,7 @@ private:
* @param conf configuration number to activate (usually 1) * @param conf configuration number to activate (usually 1)
*/ */
USB_TYPE setConfiguration(USBDeviceConnected * dev, uint8_t conf); USB_TYPE setConfiguration(USBDeviceConnected * dev, uint8_t conf);
/** /**
* Free a specific device * Free a specific device
* *
@ -378,7 +378,7 @@ private:
bool blocking, bool blocking,
ENDPOINT_TYPE type, ENDPOINT_TYPE type,
bool write) ; bool write) ;
void fillControlBuf(uint8_t requestType, uint8_t request, uint16_t value, uint16_t index, int len) ; void fillControlBuf(uint8_t requestType, uint8_t request, uint16_t value, uint16_t index, int len) ;
void parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) ; void parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) ;
int findDevice(USBDeviceConnected * dev) ; int findDevice(USBDeviceConnected * dev) ;

View File

@ -56,7 +56,7 @@
/* /*
* Enable USB3Gmodule * Enable USB3Gmodule
*/ */
#define USBHOST_3GMODULE 1 #define USBHOST_3GMODULE 1
/* /*
* Maximum number of interfaces of a usb device * Maximum number of interfaces of a usb device

View File

@ -67,28 +67,28 @@ enum ENDPOINT_TYPE {
#define HUB_CLASS 0x09 #define HUB_CLASS 0x09
#define SERIAL_CLASS 0x0A #define SERIAL_CLASS 0x0A
// ------------------ HcControl Register --------------------- // ------------------ HcControl Register ---------------------
#define OR_CONTROL_PLE 0x00000004 #define OR_CONTROL_PLE 0x00000004
#define OR_CONTROL_CLE 0x00000010 #define OR_CONTROL_CLE 0x00000010
#define OR_CONTROL_BLE 0x00000020 #define OR_CONTROL_BLE 0x00000020
#define OR_CONTROL_HCFS 0x000000C0 #define OR_CONTROL_HCFS 0x000000C0
#define OR_CONTROL_HC_OPER 0x00000080 #define OR_CONTROL_HC_OPER 0x00000080
// ----------------- HcCommandStatus Register ----------------- // ----------------- HcCommandStatus Register -----------------
#define OR_CMD_STATUS_HCR 0x00000001 #define OR_CMD_STATUS_HCR 0x00000001
#define OR_CMD_STATUS_CLF 0x00000002 #define OR_CMD_STATUS_CLF 0x00000002
#define OR_CMD_STATUS_BLF 0x00000004 #define OR_CMD_STATUS_BLF 0x00000004
// --------------- HcInterruptStatus Register ----------------- // --------------- HcInterruptStatus Register -----------------
#define OR_INTR_STATUS_WDH 0x00000002 #define OR_INTR_STATUS_WDH 0x00000002
#define OR_INTR_STATUS_RHSC 0x00000040 #define OR_INTR_STATUS_RHSC 0x00000040
#define OR_INTR_STATUS_UE 0x00000010 #define OR_INTR_STATUS_UE 0x00000010
// --------------- HcInterruptEnable Register ----------------- // --------------- HcInterruptEnable Register -----------------
#define OR_INTR_ENABLE_WDH 0x00000002 #define OR_INTR_ENABLE_WDH 0x00000002
#define OR_INTR_ENABLE_RHSC 0x00000040 #define OR_INTR_ENABLE_RHSC 0x00000040
#define OR_INTR_ENABLE_MIE 0x80000000 #define OR_INTR_ENABLE_MIE 0x80000000
// ---------------- HcRhDescriptorA Register ------------------ // ---------------- HcRhDescriptorA Register ------------------
#define OR_RH_STATUS_LPSC 0x00010000 #define OR_RH_STATUS_LPSC 0x00010000
#define OR_RH_STATUS_DRWE 0x00008000 #define OR_RH_STATUS_DRWE 0x00008000
// -------------- HcRhPortStatus[1:NDP] Register -------------- // -------------- HcRhPortStatus[1:NDP] Register --------------
#define OR_RH_PORT_CCS 0x00000001 #define OR_RH_PORT_CCS 0x00000001
#define OR_RH_PORT_PRS 0x00000010 #define OR_RH_PORT_PRS 0x00000010
#define OR_RH_PORT_CSC 0x00010000 #define OR_RH_PORT_CSC 0x00010000
@ -100,14 +100,14 @@ enum ENDPOINT_TYPE {
#define ED_SKIP (uint32_t) (0x00001000) // Skip this ep in queue #define ED_SKIP (uint32_t) (0x00001000) // Skip this ep in queue
#define TD_ROUNDING (uint32_t) (0x00040000) // Buffer Rounding #define TD_ROUNDING (uint32_t) (0x00040000) // Buffer Rounding
#define TD_SETUP (uint32_t)(0) // Direction of Setup Packet #define TD_SETUP (uint32_t)(0) // Direction of Setup Packet
#define TD_IN (uint32_t)(0x00100000) // Direction In #define TD_IN (uint32_t)(0x00100000) // Direction In
#define TD_OUT (uint32_t)(0x00080000) // Direction Out #define TD_OUT (uint32_t)(0x00080000) // Direction Out
#define TD_DELAY_INT(x) (uint32_t)((x) << 21) // Delay Interrupt #define TD_DELAY_INT(x) (uint32_t)((x) << 21) // Delay Interrupt
#define TD_TOGGLE_0 (uint32_t)(0x02000000) // Toggle 0 #define TD_TOGGLE_0 (uint32_t)(0x02000000) // Toggle 0
#define TD_TOGGLE_1 (uint32_t)(0x03000000) // Toggle 1 #define TD_TOGGLE_1 (uint32_t)(0x03000000) // Toggle 1
#define TD_CC (uint32_t)(0xF0000000) // Completion Code #define TD_CC (uint32_t)(0xF0000000) // Completion Code
#define DEVICE_DESCRIPTOR (1) #define DEVICE_DESCRIPTOR (1)
#define CONFIGURATION_DESCRIPTOR (2) #define CONFIGURATION_DESCRIPTOR (2)
@ -115,7 +115,7 @@ enum ENDPOINT_TYPE {
#define ENDPOINT_DESCRIPTOR (5) #define ENDPOINT_DESCRIPTOR (5)
#define HID_DESCRIPTOR (33) #define HID_DESCRIPTOR (33)
// ----------- Control RequestType Fields ----------- // ----------- Control RequestType Fields -----------
#define USB_DEVICE_TO_HOST 0x80 #define USB_DEVICE_TO_HOST 0x80
#define USB_HOST_TO_DEVICE 0x00 #define USB_HOST_TO_DEVICE 0x00
#define USB_REQUEST_TYPE_CLASS 0x20 #define USB_REQUEST_TYPE_CLASS 0x20
@ -124,14 +124,14 @@ enum ENDPOINT_TYPE {
#define USB_RECIPIENT_INTERFACE 0x01 #define USB_RECIPIENT_INTERFACE 0x01
#define USB_RECIPIENT_ENDPOINT 0x02 #define USB_RECIPIENT_ENDPOINT 0x02
// -------------- USB Standard Requests -------------- // -------------- USB Standard Requests --------------
#define SET_ADDRESS 0x05 #define SET_ADDRESS 0x05
#define GET_DESCRIPTOR 0x06 #define GET_DESCRIPTOR 0x06
#define SET_CONFIGURATION 0x09 #define SET_CONFIGURATION 0x09
#define SET_INTERFACE 0x0b #define SET_INTERFACE 0x0b
#define CLEAR_FEATURE 0x01 #define CLEAR_FEATURE 0x01
// -------------- USB Descriptor Length -------------- // -------------- USB Descriptor Length --------------
#define DEVICE_DESCRIPTOR_LENGTH 0x12 #define DEVICE_DESCRIPTOR_LENGTH 0x12
#define CONFIGURATION_DESCRIPTOR_LENGTH 0x09 #define CONFIGURATION_DESCRIPTOR_LENGTH 0x09
@ -145,7 +145,7 @@ typedef struct HCTD {
uint32_t dummy[3]; // padding uint32_t dummy[3]; // padding
} PACKED HCTD; } PACKED HCTD;
// ----------- HostController EndPoint Descriptor ------------- // ----------- HostController EndPoint Descriptor -------------
typedef struct hcEd { typedef struct hcEd {
__IO uint32_t control; // Endpoint descriptor control __IO uint32_t control; // Endpoint descriptor control
__IO HCTD * tailTD; // Physical address of tail in Transfer descriptor list __IO HCTD * tailTD; // Physical address of tail in Transfer descriptor list
@ -154,73 +154,73 @@ typedef struct hcEd {
} PACKED HCED; } PACKED HCED;
// ----------- Host Controller Communication Area ------------ // ----------- Host Controller Communication Area ------------
typedef struct hcca { typedef struct hcca {
__IO uint32_t IntTable[32]; // Interrupt Table __IO uint32_t IntTable[32]; // Interrupt Table
__IO uint32_t FrameNumber; // Frame Number __IO uint32_t FrameNumber; // Frame Number
__IO uint32_t DoneHead; // Done Head __IO uint32_t DoneHead; // Done Head
volatile uint8_t Reserved[116]; // Reserved for future use volatile uint8_t Reserved[116]; // Reserved for future use
volatile uint8_t Unknown[4]; // Unused volatile uint8_t Unknown[4]; // Unused
} PACKED HCCA; } PACKED HCCA;
typedef struct { typedef struct {
uint8_t bLength; uint8_t bLength;
uint8_t bDescriptorType; uint8_t bDescriptorType;
uint16_t bcdUSB; uint16_t bcdUSB;
uint8_t bDeviceClass; uint8_t bDeviceClass;
uint8_t bDeviceSubClass; uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol; uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize; uint8_t bMaxPacketSize;
uint16_t idVendor; uint16_t idVendor;
uint16_t idProduct; uint16_t idProduct;
uint16_t bcdDevice; uint16_t bcdDevice;
uint8_t iManufacturer; uint8_t iManufacturer;
uint8_t iProduct; uint8_t iProduct;
uint8_t iSerialNumber; uint8_t iSerialNumber;
uint8_t bNumConfigurations; uint8_t bNumConfigurations;
} PACKED DeviceDescriptor; } PACKED DeviceDescriptor;
typedef struct { typedef struct {
uint8_t bLength; uint8_t bLength;
uint8_t bDescriptorType; uint8_t bDescriptorType;
uint16_t wTotalLength; uint16_t wTotalLength;
uint8_t bNumInterfaces; uint8_t bNumInterfaces;
uint8_t bConfigurationValue; uint8_t bConfigurationValue;
uint8_t iConfiguration; uint8_t iConfiguration;
uint8_t bmAttributes; uint8_t bmAttributes;
uint8_t bMaxPower; uint8_t bMaxPower;
} PACKED ConfigurationDescriptor; } PACKED ConfigurationDescriptor;
typedef struct { typedef struct {
uint8_t bLength; uint8_t bLength;
uint8_t bDescriptorType; uint8_t bDescriptorType;
uint8_t bInterfaceNumber; uint8_t bInterfaceNumber;
uint8_t bAlternateSetting; uint8_t bAlternateSetting;
uint8_t bNumEndpoints; uint8_t bNumEndpoints;
uint8_t bInterfaceClass; uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass; uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol; uint8_t bInterfaceProtocol;
uint8_t iInterface; uint8_t iInterface;
} InterfaceDescriptor; } InterfaceDescriptor;
typedef struct { typedef struct {
uint8_t bLength; uint8_t bLength;
uint8_t bDescriptorType; uint8_t bDescriptorType;
uint8_t bEndpointAddress; uint8_t bEndpointAddress;
uint8_t bmAttributes; uint8_t bmAttributes;
uint16_t wMaxPacketSize; uint16_t wMaxPacketSize;
uint8_t bInterval; uint8_t bInterval;
} EndpointDescriptor; } EndpointDescriptor;
typedef struct { typedef struct {
uint8_t bDescLength; uint8_t bDescLength;
uint8_t bDescriptorType; uint8_t bDescriptorType;
uint8_t bNbrPorts; uint8_t bNbrPorts;
uint16_t wHubCharacteristics; uint16_t wHubCharacteristics;
uint8_t bPwrOn2PwrGood; uint8_t bPwrOn2PwrGood;
uint8_t bHubContrCurrent; uint8_t bHubContrCurrent;
uint8_t DeviceRemovable; uint8_t DeviceRemovable;
uint8_t PortPweCtrlMak; uint8_t PortPweCtrlMak;
} HubDescriptor; } HubDescriptor;
#endif #endif

View File

@ -45,12 +45,12 @@ bool WANDongle::tryConnect()
USB_DBG("Trying to connect device"); USB_DBG("Trying to connect device");
if (dev_connected) { if (dev_connected) {
USB_DBG("Device is already connected!"); USB_DBG("Device is already connected!");
return true; return true;
} }
m_pInitializer = NULL; m_pInitializer = NULL;
//Protect from concurrent access from USB thread //Protect from concurrent access from USB thread
USBHost::Lock lock(host); USBHost::Lock lock(host);
@ -59,16 +59,16 @@ bool WANDongle::tryConnect()
if ((dev = host->getDevice(i)) != NULL) if ((dev = host->getDevice(i)) != NULL)
{ {
m_pInitializer = NULL; //Will be set in setVidPid callback m_pInitializer = NULL; //Will be set in setVidPid callback
USB_DBG("Enumerate"); USB_DBG("Enumerate");
int ret = host->enumerate(dev, this); int ret = host->enumerate(dev, this);
if(ret) if(ret)
{ {
return false; return false;
} }
USB_DBG("Device has VID:%04x PID:%04x", dev->getVid(), dev->getPid()); USB_DBG("Device has VID:%04x PID:%04x", dev->getVid(), dev->getPid());
if(m_pInitializer) //If an initializer has been found if(m_pInitializer) //If an initializer has been found
{ {
USB_DBG("m_pInitializer=%p", m_pInitializer); USB_DBG("m_pInitializer=%p", m_pInitializer);
@ -90,18 +90,18 @@ bool WANDongle::tryConnect()
USB_DBG("Ep %p", m_pInitializer->getEp(dev, j, true)); USB_DBG("Ep %p", m_pInitializer->getEp(dev, j, true));
m_serial[j].connect( dev, m_pInitializer->getEp(dev, j, false), m_pInitializer->getEp(dev, j, true) ); m_serial[j].connect( dev, m_pInitializer->getEp(dev, j, false), m_pInitializer->getEp(dev, j, true) );
} }
USB_DBG("Device connected"); USB_DBG("Device connected");
dev_connected = true; dev_connected = true;
return true; return true;
} }
else if ((dev->getVid() == m_pInitializer->getMSDVid()) && (dev->getPid() == m_pInitializer->getMSDPid())) else if ((dev->getVid() == m_pInitializer->getMSDVid()) && (dev->getPid() == m_pInitializer->getMSDPid()))
{ {
USB_DBG("Vodafone K3370 dongle detected in MSD mode"); USB_DBG("Vodafone K3370 dongle detected in MSD mode");
//Try to switch //Try to switch
if( m_pInitializer->switchMode(dev) ) if( m_pInitializer->switchMode(dev) )
{ {
USB_DBG("Switched OK"); USB_DBG("Switched OK");

View File

@ -58,47 +58,47 @@ public:
* @return true if a serial device is connected * @return true if a serial device is connected
*/ */
bool connected(); bool connected();
/* /*
* Try to connect device * Try to connect device
* *
* * @return true if connection was successful * * @return true if connection was successful
*/ */
bool tryConnect(); bool tryConnect();
/* /*
* Disconnect device * Disconnect device
* *
* * @return true if disconnection was successful * * @return true if disconnection was successful
*/ */
bool disconnect(); bool disconnect();
int getDongleType(); int getDongleType();
IUSBHostSerial& getSerial(int index); IUSBHostSerial& getSerial(int index);
int getSerialCount(); int getSerialCount();
bool addInitializer(WANDongleInitializer* pInitializer); bool addInitializer(WANDongleInitializer* pInitializer);
//From IUSBEnumerator //From IUSBEnumerator
virtual void setVidPid(uint16_t vid, uint16_t pid); virtual void setVidPid(uint16_t vid, uint16_t pid);
virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
protected: protected:
USBHost * host; USBHost * host;
USBDeviceConnected * dev; USBDeviceConnected * dev;
bool dev_connected; bool dev_connected;
WANDongleInitializer* m_pInitializer; WANDongleInitializer* m_pInitializer;
void init(); void init();
WANDongleSerialPort m_serial[WANDONGLE_MAX_SERIAL_PORTS]; WANDongleSerialPort m_serial[WANDONGLE_MAX_SERIAL_PORTS];
int m_serialCount; int m_serialCount;
int m_totalInitializers; int m_totalInitializers;
WANDongleInitializer* m_Initializers[WANDONGLE_MAX_INITIALIZERS]; WANDongleInitializer* m_Initializers[WANDONGLE_MAX_INITIALIZERS];
}; };

View File

@ -40,29 +40,29 @@ protected:
WANDongleInitializer(USBHost* pHost) { m_pHost = pHost; } WANDongleInitializer(USBHost* pHost) { m_pHost = pHost; }
USBHost* m_pHost; USBHost* m_pHost;
uint8_t m_serialIntfMap[WANDONGLE_MAX_SERIAL_PORTS]; uint8_t m_serialIntfMap[WANDONGLE_MAX_SERIAL_PORTS];
public: public:
virtual ~WANDongleInitializer() {} virtual ~WANDongleInitializer() {}
virtual uint16_t getMSDVid() = 0; virtual uint16_t getMSDVid() = 0;
virtual uint16_t getMSDPid() = 0; virtual uint16_t getMSDPid() = 0;
virtual uint16_t getSerialVid() = 0; virtual uint16_t getSerialVid() = 0;
virtual uint16_t getSerialPid() = 0; virtual uint16_t getSerialPid() = 0;
virtual bool switchMode(USBDeviceConnected* pDev) = 0; virtual bool switchMode(USBDeviceConnected* pDev) = 0;
virtual USBEndpoint* getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx) { virtual USBEndpoint* getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx) {
return pDev->getEndpoint(m_serialIntfMap[serialPortNumber], BULK_ENDPOINT, tx ? OUT : IN, 0); return pDev->getEndpoint(m_serialIntfMap[serialPortNumber], BULK_ENDPOINT, tx ? OUT : IN, 0);
} }
virtual int getSerialPortCount() = 0; virtual int getSerialPortCount() = 0;
virtual void setVidPid(uint16_t vid, uint16_t pid) = 0; virtual void setVidPid(uint16_t vid, uint16_t pid) = 0;
virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) = 0; //Must return true if the interface should be parsed virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) = 0; //Must return true if the interface should be parsed
virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) = 0; //Must return true if the endpoint will be used virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) = 0; //Must return true if the endpoint will be used
virtual int getType() = 0; virtual int getType() = 0;
virtual uint8_t getSerialIntf(int index) { return m_serialIntfMap[index]; } virtual uint8_t getSerialIntf(int index) { return m_serialIntfMap[index]; }

View File

@ -58,7 +58,7 @@ void WANDongleSerialPort::reset()
buf_in_read_pos = 0; buf_in_read_pos = 0;
lock_rx = false; lock_rx = false;
cb_rx_pending = false; cb_rx_pending = false;
tx_mtx.unlock(); tx_mtx.unlock();
rx_mtx.unlock(); rx_mtx.unlock();
} }
@ -73,7 +73,7 @@ int WANDongleSerialPort::readPacket()
rx_mtx.unlock(); rx_mtx.unlock();
return -1; return -1;
} }
if( bulk_in == NULL ) if( bulk_in == NULL )
{ {
USB_WARN("Port is disconnected"); USB_WARN("Port is disconnected");
@ -105,7 +105,7 @@ int WANDongleSerialPort::writePacket()
tx_mtx.unlock(); tx_mtx.unlock();
return -1; return -1;
} }
if( bulk_out == NULL ) if( bulk_out == NULL )
{ {
USB_WARN("Port is disconnected"); USB_WARN("Port is disconnected");

View File

@ -42,11 +42,11 @@ public:
* *
*/ */
WANDongleSerialPort(); WANDongleSerialPort();
void init( USBHost* pHost ); void init( USBHost* pHost );
void connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp ); void connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp );
void disconnect( ); void disconnect( );
/* /*
@ -89,13 +89,13 @@ public:
* @param pListener instance of the listener deriving from the IUSBHostSerialListener * @param pListener instance of the listener deriving from the IUSBHostSerialListener
*/ */
virtual void attach(IUSBHostSerialListener* pListener); virtual void attach(IUSBHostSerialListener* pListener);
/** /**
* Enable or disable readable/writeable callbacks * Enable or disable readable/writeable callbacks
*/ */
virtual void setupIrq(bool en, IrqType irq = RxIrq); virtual void setupIrq(bool en, IrqType irq = RxIrq);
protected: protected:
USBEndpoint * bulk_in; USBEndpoint * bulk_in;
USBEndpoint * bulk_out; USBEndpoint * bulk_out;
@ -117,11 +117,11 @@ protected:
volatile bool cb_rx_en; volatile bool cb_rx_en;
volatile bool cb_rx_pending; volatile bool cb_rx_pending;
Mutex rx_mtx; Mutex rx_mtx;
IUSBHostSerialListener* listener; IUSBHostSerialListener* listener;
void reset(); void reset();
void rxHandler(); void rxHandler();
void txHandler(); void txHandler();

View File

@ -18,7 +18,7 @@
#if USBHOST_KEYBOARD #if USBHOST_KEYBOARD
static uint8_t keymap[4][0x39] = { static uint8_t keymap[4][0x39] = {
{ 0, 0, 0, 0, 'a', 'b' /*0x05*/, { 0, 0, 0, 0, 'a', 'b' /*0x05*/,
'c', 'd', 'e', 'f', 'g' /*0x0a*/, 'c', 'd', 'e', 'f', 'g' /*0x0a*/,
'h', 'i', 'j', 'k', 'l'/*0x0f*/, 'h', 'i', 'j', 'k', 'l'/*0x0f*/,
@ -100,30 +100,30 @@ bool USBHostKeyboard::connected() {
bool USBHostKeyboard::connect() { bool USBHostKeyboard::connect() {
if (dev_connected) { if (dev_connected) {
return true; return true;
} }
for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
if ((dev = host->getDevice(i)) != NULL) { if ((dev = host->getDevice(i)) != NULL) {
if (host->enumerate(dev, this)) if (host->enumerate(dev, this))
break; break;
if (keyboard_device_found) { if (keyboard_device_found) {
int_in = dev->getEndpoint(keyboard_intf, INTERRUPT_ENDPOINT, IN); int_in = dev->getEndpoint(keyboard_intf, INTERRUPT_ENDPOINT, IN);
if (!int_in) if (!int_in)
break; break;
USB_INFO("New Keyboard device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, keyboard_intf); USB_INFO("New Keyboard device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, keyboard_intf);
dev->setName("Keyboard", keyboard_intf); dev->setName("Keyboard", keyboard_intf);
host->registerDriver(dev, keyboard_intf, this, &USBHostKeyboard::init); host->registerDriver(dev, keyboard_intf, this, &USBHostKeyboard::init);
int_in->attach(this, &USBHostKeyboard::rxHandler); int_in->attach(this, &USBHostKeyboard::rxHandler);
host->interruptRead(dev, int_in, report, int_in->getSize(), false); host->interruptRead(dev, int_in, report, int_in->getSize(), false);
dev_connected = true; dev_connected = true;
return true; return true;
} }

View File

@ -23,12 +23,12 @@
#include "USBHost.h" #include "USBHost.h"
/** /**
* A class to communicate a USB keyboard * A class to communicate a USB keyboard
*/ */
class USBHostKeyboard : public IUSBEnumerator { class USBHostKeyboard : public IUSBEnumerator {
public: public:
/** /**
* Constructor * Constructor
*/ */
@ -83,7 +83,7 @@ private:
uint8_t report[9]; uint8_t report[9];
int keyboard_intf; int keyboard_intf;
bool keyboard_device_found; bool keyboard_device_found;
bool dev_connected; bool dev_connected;
void rxHandler(); void rxHandler();
@ -92,7 +92,7 @@ private:
void (*onKeyCode)(uint8_t key, uint8_t modifier); void (*onKeyCode)(uint8_t key, uint8_t modifier);
int report_id; int report_id;
void init(); void init();
}; };

View File

@ -35,7 +35,7 @@ void USBHostMouse::init() {
dev_connected = false; dev_connected = false;
mouse_device_found = false; mouse_device_found = false;
mouse_intf = -1; mouse_intf = -1;
buttons = 0; buttons = 0;
x = 0; x = 0;
y = 0; y = 0;
@ -51,26 +51,26 @@ bool USBHostMouse::connect() {
if (dev_connected) { if (dev_connected) {
return true; return true;
} }
for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
if ((dev = host->getDevice(i)) != NULL) { if ((dev = host->getDevice(i)) != NULL) {
if(host->enumerate(dev, this)) if(host->enumerate(dev, this))
break; break;
if (mouse_device_found) { if (mouse_device_found) {
int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN); int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN);
if (!int_in) if (!int_in)
break; break;
USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, mouse_intf); USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, mouse_intf);
dev->setName("Mouse", mouse_intf); dev->setName("Mouse", mouse_intf);
host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init); host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init);
int_in->attach(this, &USBHostMouse::rxHandler); int_in->attach(this, &USBHostMouse::rxHandler);
host->interruptRead(dev, int_in, report, int_in->getSize(), false); host->interruptRead(dev, int_in, report, int_in->getSize(), false);
dev_connected = true; dev_connected = true;
return true; return true;
} }
@ -82,33 +82,33 @@ bool USBHostMouse::connect() {
void USBHostMouse::rxHandler() { void USBHostMouse::rxHandler() {
int len_listen = int_in->getSize(); int len_listen = int_in->getSize();
if (onUpdate) { if (onUpdate) {
(*onUpdate)(report[0] & 0x07, report[1], report[2], report[3]); (*onUpdate)(report[0] & 0x07, report[1], report[2], report[3]);
} }
if (onButtonUpdate && (buttons != (report[0] & 0x07))) { if (onButtonUpdate && (buttons != (report[0] & 0x07))) {
(*onButtonUpdate)(report[0] & 0x07); (*onButtonUpdate)(report[0] & 0x07);
} }
if (onXUpdate && (x != report[1])) { if (onXUpdate && (x != report[1])) {
(*onXUpdate)(report[1]); (*onXUpdate)(report[1]);
} }
if (onYUpdate && (y != report[2])) { if (onYUpdate && (y != report[2])) {
(*onYUpdate)(report[2]); (*onYUpdate)(report[2]);
} }
if (onZUpdate && (z != report[3])) { if (onZUpdate && (z != report[3])) {
(*onZUpdate)(report[3]); (*onZUpdate)(report[3]);
} }
// update mouse state // update mouse state
buttons = report[0] & 0x07; buttons = report[0] & 0x07;
x = report[1]; x = report[1];
y = report[2]; y = report[2];
z = report[3]; z = report[3];
if (dev) if (dev)
host->interruptRead(dev, int_in, report, len_listen, false); host->interruptRead(dev, int_in, report, len_listen, false);
} }

View File

@ -23,7 +23,7 @@
#include "USBHost.h" #include "USBHost.h"
/** /**
* A class to communicate a USB mouse * A class to communicate a USB mouse
*/ */
class USBHostMouse : public IUSBEnumerator { class USBHostMouse : public IUSBEnumerator {
@ -58,7 +58,7 @@ public:
onUpdate = ptr; onUpdate = ptr;
} }
} }
/** /**
* Attach a callback called when the button state changes * Attach a callback called when the button state changes
* *
@ -69,7 +69,7 @@ public:
onButtonUpdate = ptr; onButtonUpdate = ptr;
} }
} }
/** /**
* Attach a callback called when the X axis value changes * Attach a callback called when the X axis value changes
* *
@ -80,7 +80,7 @@ public:
onXUpdate = ptr; onXUpdate = ptr;
} }
} }
/** /**
* Attach a callback called when the Y axis value changes * Attach a callback called when the Y axis value changes
* *
@ -91,7 +91,7 @@ public:
onYUpdate = ptr; onYUpdate = ptr;
} }
} }
/** /**
* Attach a callback called when the Z axis value changes (scrolling) * Attach a callback called when the Z axis value changes (scrolling)
* *
@ -114,7 +114,7 @@ private:
USBDeviceConnected * dev; USBDeviceConnected * dev;
USBEndpoint * int_in; USBEndpoint * int_in;
uint8_t report[4]; uint8_t report[4];
bool dev_connected; bool dev_connected;
bool mouse_device_found; bool mouse_device_found;
int mouse_intf; int mouse_intf;

View File

@ -64,7 +64,7 @@ void USBHostHub::init() {
hub_device_found = false; hub_device_found = false;
nb_port = 0; nb_port = 0;
hub_characteristics = 0; hub_characteristics = 0;
for (int i = 0; i < MAX_HUB_PORT; i++) { for (int i = 0; i < MAX_HUB_PORT; i++) {
device_children[i] = NULL; device_children[i] = NULL;
} }
@ -80,52 +80,52 @@ bool USBHostHub::connected()
} }
bool USBHostHub::connect(USBDeviceConnected * dev) bool USBHostHub::connect(USBDeviceConnected * dev)
{ {
if (dev_connected) { if (dev_connected) {
return true; return true;
} }
if(host->enumerate(dev, this)) { if(host->enumerate(dev, this)) {
init(); init();
return false; return false;
} }
if (hub_device_found) { if (hub_device_found) {
this->dev = dev; this->dev = dev;
int_in = dev->getEndpoint(hub_intf, INTERRUPT_ENDPOINT, IN); int_in = dev->getEndpoint(hub_intf, INTERRUPT_ENDPOINT, IN);
if (!int_in) { if (!int_in) {
init(); init();
return false; return false;
} }
USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, hub_intf); USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, hub_intf);
dev->setName("Hub", hub_intf); dev->setName("Hub", hub_intf);
host->registerDriver(dev, hub_intf, this, &USBHostHub::disconnect); host->registerDriver(dev, hub_intf, this, &USBHostHub::disconnect);
int_in->attach(this, &USBHostHub::rxHandler); int_in->attach(this, &USBHostHub::rxHandler);
// get HUB descriptor // get HUB descriptor
host->controlRead( dev, host->controlRead( dev,
USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS, USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS,
GET_DESCRIPTOR, GET_DESCRIPTOR,
0x29 << 8, 0, buf, sizeof(HubDescriptor)); 0x29 << 8, 0, buf, sizeof(HubDescriptor));
nb_port = buf[2]; nb_port = buf[2];
hub_characteristics = buf[3]; hub_characteristics = buf[3];
USB_DBG("Hub has %d port", nb_port); USB_DBG("Hub has %d port", nb_port);
for (uint8_t j = 1; j <= nb_port; j++) { for (uint8_t j = 1; j <= nb_port; j++) {
setPortFeature(PORT_POWER_FEATURE, j); setPortFeature(PORT_POWER_FEATURE, j);
} }
wait_ms(buf[5]*2); wait_ms(buf[5]*2);
host->interruptRead(dev, int_in, buf, 1, false); host->interruptRead(dev, int_in, buf, 1, false);
dev_connected = true; dev_connected = true;
return true; return true;
} }
return false; return false;
} }
@ -184,7 +184,7 @@ void USBHostHub::rxHandler() {
for (int port = 1; port <= nb_port; port++) { for (int port = 1; port <= nb_port; port++) {
status = getPortStatus(port); status = getPortStatus(port);
USB_DBG("[hub handler hub: %d] status port %d [hub: %p]: 0x%X", dev->getHub(), port, dev, status); USB_DBG("[hub handler hub: %d] status port %d [hub: %p]: 0x%X", dev->getHub(), port, dev, status);
// if connection status has changed // if connection status has changed
if (status & C_PORT_CONNECTION) { if (status & C_PORT_CONNECTION) {
if (status & PORT_CONNECTION) { if (status & PORT_CONNECTION) {
@ -194,18 +194,18 @@ void USBHostHub::rxHandler() {
USB_DBG("[hub handler hub: %d - port: %d] device disconnected", dev->getHub(), port); USB_DBG("[hub handler hub: %d - port: %d] device disconnected", dev->getHub(), port);
host->deviceDisconnected(dev->getHub() + 1, port, this, 0); host->deviceDisconnected(dev->getHub() + 1, port, this, 0);
} }
clearPortFeature(C_PORT_CONNECTION_FEATURE, port); clearPortFeature(C_PORT_CONNECTION_FEATURE, port);
} }
if (status & C_PORT_RESET) { if (status & C_PORT_RESET) {
clearPortFeature(C_PORT_RESET_FEATURE, port); clearPortFeature(C_PORT_RESET_FEATURE, port);
} }
if (status & C_PORT_ENABLE) { if (status & C_PORT_ENABLE) {
clearPortFeature(C_PORT_ENABLE_FEATURE, port); clearPortFeature(C_PORT_ENABLE_FEATURE, port);
} }
if ((status & PORT_OVER_CURRENT)) { if ((status & PORT_OVER_CURRENT)) {
USB_ERR("OVER CURRENT DETECTED\r\n"); USB_ERR("OVER CURRENT DETECTED\r\n");
clearPortFeature(PORT_OVER_CURRENT, port); clearPortFeature(PORT_OVER_CURRENT, port);

View File

@ -28,7 +28,7 @@ class USBHost;
class USBDeviceConnected; class USBDeviceConnected;
class USBEndpoint; class USBEndpoint;
/** /**
* A class to use a USB Hub * A class to use a USB Hub
*/ */
class USBHostHub : public IUSBEnumerator { class USBHostHub : public IUSBEnumerator {
@ -52,7 +52,7 @@ public:
* @return true if connection was successful * @return true if connection was successful
*/ */
bool connect(USBDeviceConnected * dev); bool connect(USBDeviceConnected * dev);
/** /**
* Automatically called by USBHost when a device * Automatically called by USBHost when a device
* has been enumerated by usb_thread * has been enumerated by usb_thread
@ -60,7 +60,7 @@ public:
* @param dev device connected * @param dev device connected
*/ */
void deviceConnected(USBDeviceConnected * dev); void deviceConnected(USBDeviceConnected * dev);
/** /**
* Automatically called by USBHost when a device * Automatically called by USBHost when a device
* has been disconnected from this hub * has been disconnected from this hub
@ -68,21 +68,21 @@ public:
* @param dev device disconnected * @param dev device disconnected
*/ */
void deviceDisconnected(USBDeviceConnected * dev); void deviceDisconnected(USBDeviceConnected * dev);
/** /**
* Rest a specific port * Rest a specific port
* *
* @param port port number * @param port port number
*/ */
void portReset(uint8_t port); void portReset(uint8_t port);
/* /*
* Called by USBHost to set the instance of USBHost * Called by USBHost to set the instance of USBHost
* *
* @param host host instance * @param host host instance
*/ */
void setHost(USBHost * host); void setHost(USBHost * host);
/** /**
* Called by USBhost when a hub has been disconnected * Called by USBhost when a hub has been disconnected
*/ */
@ -114,7 +114,7 @@ private:
uint32_t getPortStatus(uint8_t port); uint32_t getPortStatus(uint8_t port);
USBDeviceConnected * device_children[MAX_HUB_PORT]; USBDeviceConnected * device_children[MAX_HUB_PORT];
void init(); void init();
void disconnect(); void disconnect();

View File

@ -65,19 +65,19 @@ bool USBHostMSD::connect()
for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
if ((dev = host->getDevice(i)) != NULL) { if ((dev = host->getDevice(i)) != NULL) {
USB_DBG("Trying to connect MSD device\r\n"); USB_DBG("Trying to connect MSD device\r\n");
if(host->enumerate(dev, this)) if(host->enumerate(dev, this))
break; break;
if (msd_device_found) { if (msd_device_found) {
bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN); bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN);
bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT); bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT);
if (!bulk_in || !bulk_out) if (!bulk_in || !bulk_out)
continue; continue;
USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, msd_intf); USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, msd_intf);
dev->setName("MSD", msd_intf); dev->setName("MSD", msd_intf);
host->registerDriver(dev, msd_intf, this, &USBHostMSD::init); host->registerDriver(dev, msd_intf, this, &USBHostMSD::init);
@ -219,7 +219,7 @@ int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t
if (data) { if (data) {
USB_DBG("data stage"); USB_DBG("data stage");
if (flags == HOST_TO_DEVICE) { if (flags == HOST_TO_DEVICE) {
res = host->bulkWrite(dev, bulk_out, data, transfer_len); res = host->bulkWrite(dev, bulk_out, data, transfer_len);
if (checkResult(res, bulk_out)) if (checkResult(res, bulk_out))
return -1; return -1;
@ -242,7 +242,7 @@ int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t
if (csw.Signature != CSW_SIGNATURE) { if (csw.Signature != CSW_SIGNATURE) {
return -1; return -1;
} }
USB_DBG("recv csw: status: %d", csw.Status); USB_DBG("recv csw: status: %d", csw.Status);
// ModeSense? // ModeSense?
@ -250,27 +250,27 @@ int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t
USB_DBG("request mode sense"); USB_DBG("request mode sense");
return SCSIRequestSense(); return SCSIRequestSense();
} }
// perform reset recovery // perform reset recovery
if ((csw.Status == 2) && (cmd[0] != 0x03)) { if ((csw.Status == 2) && (cmd[0] != 0x03)) {
// send Bulk-Only Mass Storage Reset request // send Bulk-Only Mass Storage Reset request
res = host->controlWrite( dev, res = host->controlWrite( dev,
USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
BO_MASS_STORAGE_RESET, BO_MASS_STORAGE_RESET,
0, msd_intf, NULL, 0); 0, msd_intf, NULL, 0);
// unstall both endpoints // unstall both endpoints
res = host->controlWrite( dev, res = host->controlWrite( dev,
USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
CLEAR_FEATURE, CLEAR_FEATURE,
0, bulk_in->getAddress(), NULL, 0); 0, bulk_in->getAddress(), NULL, 0);
res = host->controlWrite( dev, res = host->controlWrite( dev,
USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD, USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
CLEAR_FEATURE, CLEAR_FEATURE,
0, bulk_out->getAddress(), NULL, 0); 0, bulk_out->getAddress(), NULL, 0);
} }
return csw.Status; return csw.Status;
@ -304,20 +304,20 @@ int USBHostMSD::getMaxLun() {
int USBHostMSD::disk_initialize() { int USBHostMSD::disk_initialize() {
USB_DBG("FILESYSTEM: init"); USB_DBG("FILESYSTEM: init");
U16 i, timeout = 10; U16 i, timeout = 10;
getMaxLun(); getMaxLun();
for (i = 0; i < timeout; i++) { for (i = 0; i < timeout; i++) {
Thread::wait(100); Thread::wait(100);
if (!testUnitReady()) if (!testUnitReady())
break; break;
} }
if (i == timeout) { if (i == timeout) {
disk_init = false; disk_init = false;
return -1; return -1;
} }
inquiry(0, 0); inquiry(0, 0);
disk_init = 1; disk_init = 1;
return readCapacity(); return readCapacity();

View File

@ -24,7 +24,7 @@
#include "USBHost.h" #include "USBHost.h"
#include "FATFileSystem.h" #include "FATFileSystem.h"
/** /**
* A class to communicate a USB flash disk * A class to communicate a USB flash disk
*/ */
class USBHostMSD : public IUSBEnumerator, public FATFileSystem { class USBHostMSD : public IUSBEnumerator, public FATFileSystem {
@ -109,7 +109,7 @@ private:
int msd_intf; int msd_intf;
bool msd_device_found; bool msd_device_found;
bool disk_init; bool disk_init;
void init(); void init();
}; };

View File

@ -24,7 +24,7 @@
template<typename T, int size> template<typename T, int size>
class MtxCircBuffer { class MtxCircBuffer {
public: public:
MtxCircBuffer() { MtxCircBuffer() {
write = 0; write = 0;
read = 0; read = 0;
@ -43,7 +43,7 @@ public:
mtx.unlock(); mtx.unlock();
return r; return r;
} }
void flush() { void flush() {
write = 0; write = 0;
read = 0; read = 0;

View File

@ -26,7 +26,7 @@
#if (USBHOST_SERIAL <= 1) #if (USBHOST_SERIAL <= 1)
USBHostSerial::USBHostSerial() USBHostSerial::USBHostSerial()
{ {
host = USBHost::getHostInst(); host = USBHost::getHostInst();
ports_found = 0; ports_found = 0;
@ -46,9 +46,9 @@ void USBHostSerial::disconnect(void)
bool USBHostSerial::connect() { bool USBHostSerial::connect() {
if (dev) if (dev)
{ {
for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
{ {
USBDeviceConnected* d = host->getDevice(i); USBDeviceConnected* d = host->getDevice(i);
if (dev == d) if (dev == d)
@ -56,15 +56,15 @@ bool USBHostSerial::connect() {
} }
disconnect(); disconnect();
} }
for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
{ {
USBDeviceConnected* d = host->getDevice(i); USBDeviceConnected* d = host->getDevice(i);
if (d != NULL) { if (d != NULL) {
USB_DBG("Trying to connect serial device \r\n"); USB_DBG("Trying to connect serial device \r\n");
if(host->enumerate(d, this)) if(host->enumerate(d, this))
break; break;
USBEndpoint* bulk_in = d->getEndpoint(port_intf, BULK_ENDPOINT, IN); USBEndpoint* bulk_in = d->getEndpoint(port_intf, BULK_ENDPOINT, IN);
USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT); USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT);
if (bulk_in && bulk_out) if (bulk_in && bulk_out)
@ -84,7 +84,7 @@ bool USBHostSerial::connect() {
/*virtual*/ bool USBHostSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed /*virtual*/ bool USBHostSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
{ {
if (!ports_found && if (!ports_found &&
CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) { CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
port_intf = intf_nb; port_intf = intf_nb;
ports_found = true; ports_found = true;
@ -96,7 +96,7 @@ bool USBHostSerial::connect() {
/*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used /*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
{ {
if (ports_found && (intf_nb == port_intf)) { if (ports_found && (intf_nb == port_intf)) {
if (type == BULK_ENDPOINT) if (type == BULK_ENDPOINT)
return true; return true;
} }
return false; return false;
@ -106,7 +106,7 @@ bool USBHostSerial::connect() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
USBHostMultiSerial::USBHostMultiSerial() USBHostMultiSerial::USBHostMultiSerial()
{ {
host = USBHost::getHostInst(); host = USBHost::getHostInst();
dev = NULL; dev = NULL;
@ -127,7 +127,7 @@ bool USBHostMultiSerial::connected()
void USBHostMultiSerial::disconnect(void) void USBHostMultiSerial::disconnect(void)
{ {
for (int port = 0; port < USBHOST_SERIAL; port ++) for (int port = 0; port < USBHOST_SERIAL; port ++)
{ {
if (ports[port]) if (ports[port])
{ {
@ -141,9 +141,9 @@ void USBHostMultiSerial::disconnect(void)
bool USBHostMultiSerial::connect() { bool USBHostMultiSerial::connect() {
if (dev) if (dev)
{ {
for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
{ {
USBDeviceConnected* d = host->getDevice(i); USBDeviceConnected* d = host->getDevice(i);
if (dev == d) if (dev == d)
@ -151,16 +151,16 @@ bool USBHostMultiSerial::connect() {
} }
disconnect(); disconnect();
} }
for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
{ {
USBDeviceConnected* d = host->getDevice(i); USBDeviceConnected* d = host->getDevice(i);
if (d != NULL) { if (d != NULL) {
USB_DBG("Trying to connect serial device \r\n"); USB_DBG("Trying to connect serial device \r\n");
if(host->enumerate(d, this)) if(host->enumerate(d, this))
break; break;
for (int port = 0; port < ports_found; port ++) for (int port = 0; port < ports_found; port ++)
{ {
USBEndpoint* bulk_in = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN); USBEndpoint* bulk_in = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN);
USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT); USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT);
@ -186,7 +186,7 @@ bool USBHostMultiSerial::connect() {
/*virtual*/ bool USBHostMultiSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed /*virtual*/ bool USBHostMultiSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
{ {
if ((ports_found < USBHOST_SERIAL) && if ((ports_found < USBHOST_SERIAL) &&
CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) { CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
port_intf[ports_found++] = intf_nb; port_intf[ports_found++] = intf_nb;
return true; return true;
@ -197,7 +197,7 @@ bool USBHostMultiSerial::connect() {
/*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used /*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
{ {
if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) { if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) {
if (type == BULK_ENDPOINT) if (type == BULK_ENDPOINT)
return true; return true;
} }
return false; return false;
@ -209,7 +209,7 @@ bool USBHostMultiSerial::connect() {
#define SET_LINE_CODING 0x20 #define SET_LINE_CODING 0x20
USBHostSerialPort::USBHostSerialPort(): circ_buf() USBHostSerialPort::USBHostSerialPort(): circ_buf()
{ {
init(); init();
} }
@ -230,7 +230,7 @@ void USBHostSerialPort::init(void)
circ_buf.flush(); circ_buf.flush();
} }
void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev, void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev,
uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out) uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out)
{ {
host = _host; host = _host;
@ -238,7 +238,7 @@ void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev,
serial_intf = _serial_intf; serial_intf = _serial_intf;
bulk_in = _bulk_in; bulk_in = _bulk_in;
bulk_out = _bulk_out; bulk_out = _bulk_out;
USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf); USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf);
dev->setName("Serial", serial_intf); dev->setName("Serial", serial_intf);
host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init); host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init);
@ -289,7 +289,7 @@ void USBHostSerialPort::format(int bits, Parity parity, int stop_bits) {
line_coding.data_bits = bits; line_coding.data_bits = bits;
line_coding.parity = parity; line_coding.parity = parity;
line_coding.stop_bits = (stop_bits == 1) ? 0 : 2; line_coding.stop_bits = (stop_bits == 1) ? 0 : 2;
// set line coding // set line coding
host->controlWrite( dev, host->controlWrite( dev,
USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS, USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
@ -311,12 +311,12 @@ int USBHostSerialPort::_getc() {
int USBHostSerialPort::writeBuf(const char* b, int s) int USBHostSerialPort::writeBuf(const char* b, int s)
{ {
int c = 0; int c = 0;
if (bulk_out) if (bulk_out)
{ {
while (c < s) while (c < s)
{ {
int i = (s < size_bulk_out) ? s : size_bulk_out; int i = (s < size_bulk_out) ? s : size_bulk_out;
if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK) if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK)
c += i; c += i;
} }
} }
@ -326,7 +326,7 @@ int USBHostSerialPort::writeBuf(const char* b, int s)
int USBHostSerialPort::readBuf(char* b, int s) int USBHostSerialPort::readBuf(char* b, int s)
{ {
int i = 0; int i = 0;
if (bulk_in) if (bulk_in)
{ {
for (i = 0; i < s; ) for (i = 0; i < s; )
b[i++] = getc(); b[i++] = getc();

View File

@ -25,7 +25,7 @@
#include "Stream.h" #include "Stream.h"
#include "MtxCircBuffer.h" #include "MtxCircBuffer.h"
/** /**
* A class to communicate a USB virtual serial port * A class to communicate a USB virtual serial port
*/ */
class USBHostSerialPort : public Stream { class USBHostSerialPort : public Stream {
@ -39,7 +39,7 @@ public:
RxIrq, RxIrq,
TxIrq TxIrq
}; };
enum Parity { enum Parity {
None = 0, None = 0,
Odd, Odd,
@ -48,7 +48,7 @@ public:
Space Space
}; };
void connect(USBHost* _host, USBDeviceConnected * _dev, void connect(USBHost* _host, USBDeviceConnected * _dev,
uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out); uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out);
/** /**
@ -56,7 +56,7 @@ public:
* *
* @returns the number of bytes available * @returns the number of bytes available
*/ */
uint8_t available(); uint8_t available();
/** /**
* Attach a member function to call when a packet is received. * Attach a member function to call when a packet is received.
@ -90,13 +90,13 @@ public:
} }
} }
} }
/** Set the baud rate of the serial port /** Set the baud rate of the serial port
* *
* @param baudrate The baudrate of the serial port (default = 9600). * @param baudrate The baudrate of the serial port (default = 9600).
*/ */
void baud(int baudrate = 9600); void baud(int baudrate = 9600);
/** Set the transmission format used by the Serial port /** Set the transmission format used by the Serial port
* *
* @param bits The number of bits in a word (default = 8) * @param bits The number of bits in a word (default = 8)
@ -110,7 +110,7 @@ public:
protected: protected:
virtual int _getc(); virtual int _getc();
virtual int _putc(int c); virtual int _putc(int c);
private: private:
USBHost * host; USBHost * host;
USBDeviceConnected * dev; USBDeviceConnected * dev;
@ -132,7 +132,7 @@ private:
uint8_t parity; uint8_t parity;
uint8_t data_bits; uint8_t data_bits;
} PACKED LINE_CODING; } PACKED LINE_CODING;
LINE_CODING line_coding; LINE_CODING line_coding;
void rxHandler(); void rxHandler();
@ -145,18 +145,18 @@ private:
#if (USBHOST_SERIAL <= 1) #if (USBHOST_SERIAL <= 1)
class USBHostSerial : public IUSBEnumerator, public USBHostSerialPort class USBHostSerial : public IUSBEnumerator, public USBHostSerialPort
{ {
public: public:
USBHostSerial(); USBHostSerial();
/** /**
* Try to connect a serial device * Try to connect a serial device
* *
* @return true if connection was successful * @return true if connection was successful
*/ */
bool connect(); bool connect();
void disconnect(); void disconnect();
/** /**
@ -165,7 +165,7 @@ public:
* @returns true if a serial device is connected * @returns true if a serial device is connected
*/ */
bool connected(); bool connected();
protected: protected:
USBHost* host; USBHost* host;
USBDeviceConnected* dev; USBDeviceConnected* dev;
@ -176,7 +176,7 @@ protected:
virtual void setVidPid(uint16_t vid, uint16_t pid); virtual void setVidPid(uint16_t vid, uint16_t pid);
virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
private: private:
bool dev_connected; bool dev_connected;
}; };
@ -184,13 +184,13 @@ private:
#else // (USBHOST_SERIAL > 1) #else // (USBHOST_SERIAL > 1)
class USBHostMultiSerial : public IUSBEnumerator { class USBHostMultiSerial : public IUSBEnumerator {
public: public:
USBHostMultiSerial(); USBHostMultiSerial();
virtual ~USBHostMultiSerial(); virtual ~USBHostMultiSerial();
USBHostSerialPort* getPort(int port) USBHostSerialPort* getPort(int port)
{ {
return port < USBHOST_SERIAL ? ports[port] : NULL; return port < USBHOST_SERIAL ? ports[port] : NULL;
} }
/** /**
@ -199,7 +199,7 @@ public:
* @return true if connection was successful * @return true if connection was successful
*/ */
bool connect(); bool connect();
void disconnect(); void disconnect();
/** /**
@ -208,7 +208,7 @@ public:
* @returns true if a serial device is connected * @returns true if a serial device is connected
*/ */
bool connected(); bool connected();
protected: protected:
USBHost* host; USBHost* host;
USBDeviceConnected* dev; USBDeviceConnected* dev;
@ -220,7 +220,7 @@ protected:
virtual void setVidPid(uint16_t vid, uint16_t pid); virtual void setVidPid(uint16_t vid, uint16_t pid);
virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
private: private:
bool dev_connected; bool dev_connected;
}; };

View File

@ -1,240 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 <stdio.h>
#include <string.h>
#include "GapAdvertisingData.h"
/**************************************************************************/
/*!
\brief Creates a new GapAdvertisingData instance
\par EXAMPLE
\code
\endcode
*/
/**************************************************************************/
GapAdvertisingData::GapAdvertisingData(void)
{
memset(_payload, 0, GAP_ADVERTISING_DATA_MAX_PAYLOAD);
_payloadLen = 0;
_appearance = GENERIC_TAG;
}
/**************************************************************************/
/*!
Destructor
*/
/**************************************************************************/
GapAdvertisingData::~GapAdvertisingData(void)
{
}
/**************************************************************************/
/*!
\brief Adds advertising data based on the specified AD type (see
DataType)
\args[in] advDataType The Advertising 'DataType' to add
\args[in] payload Pointer to the payload contents
\args[in] len Size of the payload in bytes
\returns ble_error_t
\retval BLE_ERROR_NONE
Everything executed properly
\retval BLE_ERROR_BUFFER_OVERFLOW
The specified data would cause the advertising buffer
to overflow
\par EXAMPLE
\code
\endcode
*/
/**************************************************************************/
ble_error_t GapAdvertisingData::addData(DataType advDataType, uint8_t * payload, uint8_t len)
{
/* ToDo: Check if an AD type already exists and if the existing */
/* value is exclusive or not (flags, etc.) */
/* Make sure we don't exceed the 31 byte payload limit */
if (_payloadLen + len + 2 >= GAP_ADVERTISING_DATA_MAX_PAYLOAD)
return BLE_ERROR_BUFFER_OVERFLOW;
/* Field length */
memset(&_payload[_payloadLen], len+1, 1);
_payloadLen++;
/* Field ID */
memset(&_payload[_payloadLen], (uint8_t)advDataType, 1);
_payloadLen++;
/* Payload */
memcpy(&_payload[_payloadLen], payload, len);
_payloadLen += len;
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
\brief Helper function to add APPEARANCE data to the advertising
payload
\args[in] appearance The APPEARANCE value to add
\returns ble_error_t
\retval BLE_ERROR_NONE
Everything executed properly
\retval BLE_ERROR_BUFFER_OVERFLOW
The specified data would cause the advertising buffer
to overflow
\par EXAMPLE
\code
\endcode
*/
/**************************************************************************/
ble_error_t GapAdvertisingData::addAppearance(Appearance appearance)
{
_appearance = appearance;
return addData(GapAdvertisingData::APPEARANCE, (uint8_t*)&appearance, 2);
}
/**************************************************************************/
/*!
\brief Helper function to add FLAGS data to the advertising
payload
\args[in] flag The FLAGS value to add
\par LE_LIMITED_DISCOVERABLE
The peripheral is discoverable for a limited period of
time
\par LE_GENERAL_DISCOVERABLE
The peripheral is permanently discoverable
\par BREDR_NOT_SUPPORTED
This peripheral is a Bluetooth Low Energy only device
(no EDR support)
\returns ble_error_t
\retval BLE_ERROR_NONE
Everything executed properly
\retval BLE_ERROR_BUFFER_OVERFLOW
The specified data would cause the advertising buffer
to overflow
\par EXAMPLE
\code
\endcode
*/
/**************************************************************************/
ble_error_t GapAdvertisingData::addFlags(Flags flag)
{
return addData(GapAdvertisingData::FLAGS, (uint8_t*)&flag, 1);
}
/**************************************************************************/
/*!
\brief Helper function to add TX_POWER_LEVEL data to the
advertising payload
\args[in] flag The TX_POWER_LEVEL value to add
\returns ble_error_t
\retval BLE_ERROR_NONE
Everything executed properly
\retval BLE_ERROR_BUFFER_OVERFLOW
The specified data would cause the advertising buffer
to overflow
\par EXAMPLE
\code
\endcode
*/
/**************************************************************************/
ble_error_t GapAdvertisingData::addTxPower(int8_t txPower)
{
/* ToDo: Basic error checking to make sure txPower is in range */
return addData(GapAdvertisingData::TX_POWER_LEVEL, (uint8_t*)&txPower, 1);
}
/**************************************************************************/
/*!
\brief Clears the payload and resets the payload length counter
*/
/**************************************************************************/
void GapAdvertisingData::clear(void)
{
memset(&_payload, 0, GAP_ADVERTISING_DATA_MAX_PAYLOAD);
_payloadLen = 0;
}
/**************************************************************************/
/*!
\brief Returns a pointer to the the current payload
\returns A pointer to the payload
*/
/**************************************************************************/
uint8_t * GapAdvertisingData::getPayload(void)
{
return (_payloadLen > 0) ? _payload : NULL;
}
/**************************************************************************/
/*!
\brief Returns the current payload length (0..31 bytes)
\returns The payload length in bytes
*/
/**************************************************************************/
uint8_t GapAdvertisingData::getPayloadLen(void)
{
return _payloadLen;
}
/**************************************************************************/
/*!
\brief Returns the 16-bit appearance value for this device
\returns The 16-bit appearance value
*/
/**************************************************************************/
uint16_t GapAdvertisingData::getAppearance(void)
{
return (uint16_t)_appearance;
}

View File

@ -1,212 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __GAP_ADVERTISING_DATA_H__
#define __GAP_ADVERTISING_DATA_H__
#include "blecommon.h"
#define GAP_ADVERTISING_DATA_MAX_PAYLOAD (31)
/**************************************************************************/
/*!
\brief
This class provides several helper functions to generate properly
formatted GAP Advertising and Scan Response data payloads
\note
See Bluetooth Specification 4.0 (Vol. 3), Part C, Section 11 and 18
for further information on Advertising and Scan Response data.
\par Advertising and Scan Response Payloads
Advertising data and Scan Response data are organized around a set of
data types called 'AD types' in Bluetooth 4.0 (see the Bluetooth Core
Specification v4.0, Vol. 3, Part C, Sections 11 and 18).
\par
Each AD type has it's own standardized 'assigned number', as defined
by the Bluetooth SIG:
https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile
\par
For convenience sake, all appropriate AD types have been encapsulated
into GapAdvertisingData::DataType.
\par
Before the AD Types and their payload (if any) can be inserted into
the Advertising or Scan Response frames, they need to be formatted as
follows:
\li \c Record length (1 byte)
\li \c AD Type (1 byte)
\li \c AD payload (optional, only present if record length > 1)
\par
This class takes care of properly formatting the payload, performs
some basic checks on the payload length, and tries to avoid common
errors like adding an exclusive AD field twice in the Advertising
or Scan Response payload.
\par EXAMPLE
\code
// ToDo
\endcode
*/
/**************************************************************************/
class GapAdvertisingData
{
public:
/**********************************************************************/
/*!
\brief
A list of Advertising Data types commonly used by peripherals.
These AD types are used to describe the capabilities of the
peripheral, and get inserted inside the advertising or scan
response payloads.
\par Source
\li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 11, 18
\li \c https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile
*/
/**********************************************************************/
enum DataType
{
FLAGS = 0x01, /**< \ref Flags */
INCOMPLETE_LIST_16BIT_SERVICE_IDS = 0x02, /**< Incomplete list of 16-bit Service IDs */
COMPLETE_LIST_16BIT_SERVICE_IDS = 0x03, /**< Complete list of 16-bit Service IDs */
INCOMPLETE_LIST_32BIT_SERVICE_IDS = 0x04, /**< Incomplete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
COMPLETE_LIST_32BIT_SERVICE_IDS = 0x05, /**< Complete list of 32-bit Service IDs (not relevant for Bluetooth 4.0) */
INCOMPLETE_LIST_128BIT_SERVICE_IDS = 0x06, /**< Incomplete list of 128-bit Service IDs */
COMPLETE_LIST_128BIT_SERVICE_IDS = 0x07, /**< Complete list of 128-bit Service IDs */
SHORTENED_LOCAL_NAME = 0x08, /**< Shortened Local Name */
COMPLETE_LOCAL_NAME = 0x09, /**< Complete Local Name */
TX_POWER_LEVEL = 0x0A, /**< TX Power Level (in dBm) */
DEVICE_ID = 0x10, /**< Device ID */
SLAVE_CONNECTION_INTERVAL_RANGE = 0x12, /**< Slave Connection Interval Range */
SERVICE_DATA = 0x16, /**< Service Data */
APPEARANCE = 0x19, /**< \ref Appearance */
ADVERTISING_INTERVAL = 0x1A, /**< Advertising Interval */
MANUFACTURER_SPECIFIC_DATA = 0xFF /**< Manufacturer Specific Data */
};
/**********************************************************************/
/*!
\brief
A list of values for the FLAGS AD Type
\note
You can use more than one value in the FLAGS AD Type (ex.
LE_GENERAL_DISCOVERABLE and BREDR_NOT_SUPPORTED).
\par Source
\li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 18.1
*/
/**********************************************************************/
enum Flags
{
LE_LIMITED_DISCOVERABLE = 0x01, /**< Peripheral device is discoverable for a limited period of time */
LE_GENERAL_DISCOVERABLE = 0x02, /**< Peripheral device is discoverable at any moment */
BREDR_NOT_SUPPORTED = 0x04, /**< Peripheral device is LE only */
SIMULTANEOUS_LE_BREDR_C = 0x08, /**< Not relevant - central mode only */
SIMULTANEOUS_LE_BREDR_H = 0x10 /**< Not relevant - central mode only */
};
/**********************************************************************/
/*!
\brief
A list of values for the APPEARANCE AD Type, which describes the
physical shape or appearance of the device
\par Source
\li \c Bluetooth Core Specification Supplement, Part A, Section 1.12
\li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 12.2
\li \c https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
*/
/**********************************************************************/
enum Appearance
{
UNKNOWN = 0, /**< Unknown of unspecified appearance type */
GENERIC_PHONE = 64, /**< Generic Phone */
GENERIC_COMPUTER = 128, /**< Generic Computer */
GENERIC_WATCH = 192, /**< Generic Watch */
WATCH_SPORTS_WATCH = 193, /**< Sports Watch */
GENERIC_CLOCK = 256, /**< Generic Clock */
GENERIC_DISPLAY = 320, /**< Generic Display */
GENERIC_REMOTE_CONTROL = 384, /**< Generic Remote Control */
GENERIC_EYE_GLASSES = 448, /**< Generic Eye Glasses */
GENERIC_TAG = 512, /**< Generic Tag */
GENERIC_KEYRING = 576, /**< Generic Keyring */
GENERIC_MEDIA_PLAYER = 640, /**< Generic Media Player */
GENERIC_BARCODE_SCANNER = 704, /**< Generic Barcode Scanner */
GENERIC_THERMOMETER = 768, /**< Generic Thermometer */
THERMOMETER_EAR = 769, /**< Ear Thermometer */
GENERIC_HEART_RATE_SENSOR = 832, /**< Generic Heart Rate Sensor */
HEART_RATE_SENSOR_HEART_RATE_BELT = 833, /**< Belt Heart Rate Sensor */
GENERIC_BLOOD_PRESSURE = 896, /**< Generic Blood Pressure */
BLOOD_PRESSURE_ARM = 897, /**< Arm Blood Pressure */
BLOOD_PRESSURE_WRIST = 898, /**< Wrist Blood Pressure */
HUMAN_INTERFACE_DEVICE_HID = 960, /**< Human Interface Device (HID) */
KEYBOARD = 961, /**< Keyboard */
MOUSE = 962, /**< Mouse */
JOYSTICK = 963, /**< Joystick */
GAMEPAD = 964, /**< Gamepad */
DIGITIZER_TABLET = 965, /**< Digitizer Tablet */
CARD_READER = 966, /**< Card Read */
DIGITAL_PEN = 967, /**< Digital Pen */
BARCODE_SCANNER = 968, /**< Barcode Scanner */
GENERIC_GLUCOSE_METER = 1024, /**< Generic Glucose Meter */
GENERIC_RUNNING_WALKING_SENSOR = 1088, /**< Generic Running/Walking Sensor */
RUNNING_WALKING_SENSOR_IN_SHOE = 1089, /**< In Shoe Running/Walking Sensor */
RUNNING_WALKING_SENSOR_ON_SHOE = 1090, /**< On Shoe Running/Walking Sensor */
RUNNING_WALKING_SENSOR_ON_HIP = 1091, /**< On Hip Running/Walking Sensor */
GENERIC_CYCLING = 1152, /**< Generic Cycling */
CYCLING_CYCLING_COMPUTER = 1153, /**< Cycling Computer */
CYCLING_SPEED_SENSOR = 1154, /**< Cycling Speed Senspr */
CYCLING_CADENCE_SENSOR = 1155, /**< Cycling Cadence Sensor */
CYCLING_POWER_SENSOR = 1156, /**< Cycling Power Sensor */
CYCLING_SPEED_AND_CADENCE_SENSOR = 1157, /**< Cycling Speed and Cadence Sensor */
PULSE_OXIMETER_GENERIC = 3136, /**< Generic Pulse Oximeter */
PULSE_OXIMETER_FINGERTIP = 3137, /**< Fingertip Pulse Oximeter */
PULSE_OXIMETER_WRIST_WORN = 3138, /**< Wrist Worn Pulse Oximeter */
OUTDOOR_GENERIC = 5184, /**< Generic Outdoor */
OUTDOOR_LOCATION_DISPLAY_DEVICE = 5185, /**< Outdoor Location Display Device */
OUTDOOR_LOCATION_AND_NAVIGATION_DISPLAY_DEVICE = 5186, /**< Outdoor Location and Navigation Display Device */
OUTDOOR_LOCATION_POD = 5187, /**< Outdoor Location Pod */
OUTDOOR_LOCATION_AND_NAVIGATION_POD = 5188 /**< Outdoor Location and Navigation Pod */
};
GapAdvertisingData(void);
virtual ~GapAdvertisingData(void);
ble_error_t addData(DataType, uint8_t *, uint8_t);
ble_error_t addAppearance(Appearance appearance = GENERIC_TAG);
ble_error_t addFlags(Flags flag = LE_GENERAL_DISCOVERABLE);
ble_error_t addTxPower(int8_t txPower);
void clear(void);
uint8_t * getPayload(void);
uint8_t getPayloadLen(void);
uint16_t getAppearance(void);
private:
uint8_t _payload[GAP_ADVERTISING_DATA_MAX_PAYLOAD];
uint8_t _payloadLen;
uint16_t _appearance;
};
#endif

View File

@ -1,168 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 <stdio.h>
#include <string.h>
#include "blecommon.h"
#include "GapAdvertisingParams.h"
/**************************************************************************/
/*!
\brief
Instantiates a new GapAdvertisingParams instance
\param[in] advType
The GAP advertising mode to use for this device. Valid
values are defined in AdvertisingType:
\par ADV_NON_CONNECTABLE_UNDIRECTED
All connections to the peripheral device will be refused.
\par ADV_CONNECTABLE_DIRECTED
Only connections from a pre-defined central device will be
accepted.
\par ADV_CONNECTABLE_UNDIRECTED
Any central device can connect to this peripheral.
\par ADV_SCANNABLE_UNDIRECTED
Any central device can connect to this peripheral, and
the secondary Scan Response payload will be included or
available to central devices.
\par
See Bluetooth Core Specification 4.0 (Vol. 3), Part C,
Section 9.3 and Core Specification 4.0 (Vol. 6), Part B,
Section 2.3.1 for further information on GAP connection
modes
\param[in] interval
Advertising interval between 0x0020 and 0x4000 in 0.625ms
units (20ms to 10.24s). If using non-connectable mode
(ADV_NON_CONNECTABLE_UNDIRECTED) this min value is
0x00A0 (100ms).
\par
Increasing this value will allow central devices to detect
your peripheral faster at the expense of more power being
used by the radio due to the higher data transmit rate.
\par
This field must be set to 0 if connectionMode is equal
to ADV_CONNECTABLE_DIRECTED
\par
See Bluetooth Core Specification, Vol 3., Part C,
Appendix A for suggested advertising intervals.
\param[in] timeout
Advertising timeout between 0x1 and 0x3FFF (1 and 16383)
in seconds. Enter 0 to disable the advertising timeout.
\par EXAMPLE
\code
\endcode
*/
/**************************************************************************/
GapAdvertisingParams::GapAdvertisingParams(AdvertisingType advType, uint16_t interval, uint16_t timeout)
{
_advType = advType;
_interval = interval;
_timeout = timeout;
/* Interval checks */
if (_advType == ADV_CONNECTABLE_DIRECTED)
{
/* Interval must be 0 in directed connectable mode */
_interval = 0;
}
else if (_advType == ADV_NON_CONNECTABLE_UNDIRECTED)
{
/* Min interval is slightly larger than in other modes */
if (_interval < GAP_ADV_PARAMS_INTERVAL_MIN_NONCON)
{
_interval = GAP_ADV_PARAMS_INTERVAL_MIN_NONCON;
}
if (_interval > GAP_ADV_PARAMS_INTERVAL_MAX)
{
_interval = GAP_ADV_PARAMS_INTERVAL_MAX;
}
}
else
{
/* Stay within interval limits */
if (_interval < GAP_ADV_PARAMS_INTERVAL_MIN)
{
_interval = GAP_ADV_PARAMS_INTERVAL_MIN;
}
if (_interval > GAP_ADV_PARAMS_INTERVAL_MAX)
{
_interval = GAP_ADV_PARAMS_INTERVAL_MAX;
}
}
/* Timeout checks */
if (timeout)
{
/* Stay within timeout limits */
if (_timeout > GAP_ADV_PARAMS_TIMEOUT_MAX)
{
_timeout = GAP_ADV_PARAMS_TIMEOUT_MAX;
}
}
}
/**************************************************************************/
/*!
Destructor
*/
/**************************************************************************/
GapAdvertisingParams::~GapAdvertisingParams(void)
{
}
/**************************************************************************/
/*!
\brief returns the current Advertising Type value
*/
/**************************************************************************/
GapAdvertisingParams::AdvertisingType GapAdvertisingParams::getAdvertisingType(void)
{
return _advType;
}
/**************************************************************************/
/*!
\brief returns the current Advertising Delay (in units of 0.625ms)
*/
/**************************************************************************/
uint16_t GapAdvertisingParams::getInterval(void)
{
return _interval;
}
/**************************************************************************/
/*!
\brief returns the current Advertising Timeout (in seconds)
*/
/**************************************************************************/
uint16_t GapAdvertisingParams::getTimeout(void)
{
return _timeout;
}

View File

@ -1,89 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __GAP_ADVERTISING_PARAMS_H__
#define __GAP_ADVERTISING_PARAMS_H__
#include "blecommon.h"
#define GAP_ADV_PARAMS_INTERVAL_MIN (0x0020)
#define GAP_ADV_PARAMS_INTERVAL_MIN_NONCON (0x00A0)
#define GAP_ADV_PARAMS_INTERVAL_MAX (0x1000)
#define GAP_ADV_PARAMS_TIMEOUT_MAX (0x3FFF)
/**************************************************************************/
/*!
\brief
This class provides a wrapper for the core advertising parameters,
including the advertising type (Connectable Undirected,
Non Connectable Undirected, etc.), as well as the advertising and
timeout intervals.
\par
See the following for more information on advertising types:
\li \c Bluetooth Core Specification 4.0 (Vol. 6), Part B, Section 2.3.1
\li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 9.3
\par EXAMPLE
\code
// ToDo
\endcode
*/
/**************************************************************************/
class GapAdvertisingParams
{
public:
/**************************************************************************/
/*!
\brief
Encapsulates the peripheral advertising modes, which determine how
the device appears to other central devices in hearing range
\par
See the following for more information on advertising types:
\li \c Bluetooth Core Specification 4.0 (Vol. 6), Part B, Section 2.3.1
\li \c Bluetooth Core Specification 4.0 (Vol. 3), Part C, Section 9.3
*/
/**************************************************************************/
enum AdvertisingType
{
ADV_CONNECTABLE_UNDIRECTED, /**< Vol 3, Part C, Section 9.3.4 and Vol 6, Part B, Section 2.3.1.1 */
ADV_CONNECTABLE_DIRECTED, /**< Vol 3, Part C, Section 9.3.3 and Vol 6, Part B, Section 2.3.1.2 */
ADV_SCANNABLE_UNDIRECTED, /**< Include support for Scan Response payloads, see Vol 6, Part B, Section 2.3.1.4 */
ADV_NON_CONNECTABLE_UNDIRECTED /**< Vol 3, Part C, Section 9.3.2 and Vol 6, Part B, Section 2.3.1.3 */
};
GapAdvertisingParams(AdvertisingType advType = GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED,
uint16_t interval = GAP_ADV_PARAMS_INTERVAL_MIN_NONCON,
uint16_t timeout = 0);
virtual ~GapAdvertisingParams(void);
virtual AdvertisingType getAdvertisingType(void);
virtual uint16_t getInterval(void);
virtual uint16_t getTimeout(void);
private:
AdvertisingType _advType;
uint16_t _interval;
uint16_t _timeout;
};
#endif

View File

@ -1,65 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 <stdio.h>
#include <string.h>
#include "GattCharacteristic.h"
/**************************************************************************/
/*!
@brief Creates a new GattCharacteristic using the specified 16-bit
UUID, value length, and properties
@note The UUID value must be unique in the service and is normally >1
@param[in] id
The 16-bit UUID to use for this characteristic
@param[in] minLen
The min length in bytes of this characteristic's value
@param[in] maxLen
The max length in bytes of this characteristic's value
@param[in] props
The 8-bit bit field containing the characteristic's
properties
@section EXAMPLE
@code
// UUID = 0x2A19, Min length 2, Max len = 2, Properties = write
GattCharacteristic c = GattCharacteristic( 0x2A19, 2, 2, BLE_GATT_CHAR_PROPERTIES_WRITE );
@endcode
*/
/**************************************************************************/
GattCharacteristic::GattCharacteristic(uint16_t id, uint16_t minLen, uint16_t maxLen, uint8_t props)
{
uuid = id;
memcpy(&properties, &props, 1);
lenMin = minLen;
lenMax = maxLen;
// handle = 0;
}
/**************************************************************************/
/*!
Destructor
*/
/**************************************************************************/
GattCharacteristic::~GattCharacteristic(void)
{
}

View File

@ -1,318 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __GATT_CHARACTERISTIC_H__
#define __GATT_CHARACTERISTIC_H__
#include "blecommon.h"
#include "UUID.h"
#include "ble_gatts.h"
/* ToDo: Update to use 16-bit or 128-bit UUIDs! */
/**************************************************************************/
/*!
\brief GATT characteristic
*/
/**************************************************************************/
class GattCharacteristic
{
public:
enum
{
UUID_BATTERY_LEVEL_STATE_CHAR = 0x2A1B,
UUID_BATTERY_POWER_STATE_CHAR = 0x2A1A,
UUID_REMOVABLE_CHAR = 0x2A3A,
UUID_SERVICE_REQUIRED_CHAR = 0x2A3B,
UUID_ALERT_CATEGORY_ID_CHAR = 0x2A43,
UUID_ALERT_CATEGORY_ID_BIT_MASK_CHAR = 0x2A42,
UUID_ALERT_LEVEL_CHAR = 0x2A06,
UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR = 0x2A44,
UUID_ALERT_STATUS_CHAR = 0x2A3F,
UUID_BATTERY_LEVEL_CHAR = 0x2A19,
UUID_BLOOD_PRESSURE_FEATURE_CHAR = 0x2A49,
UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR = 0x2A35,
UUID_BODY_SENSOR_LOCATION_CHAR = 0x2A38,
UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR = 0x2A22,
UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR = 0x2A32,
UUID_BOOT_MOUSE_INPUT_REPORT_CHAR = 0x2A33,
UUID_CURRENT_TIME_CHAR = 0x2A2B,
UUID_DATE_TIME_CHAR = 0x2A08,
UUID_DAY_DATE_TIME_CHAR = 0x2A0A,
UUID_DAY_OF_WEEK_CHAR = 0x2A09,
UUID_DST_OFFSET_CHAR = 0x2A0D,
UUID_EXACT_TIME_256_CHAR = 0x2A0C,
UUID_FIRMWARE_REVISION_STRING_CHAR = 0x2A26,
UUID_GLUCOSE_FEATURE_CHAR = 0x2A51,
UUID_GLUCOSE_MEASUREMENT_CHAR = 0x2A18,
UUID_GLUCOSE_MEASUREMENT_CONTEXT_CHAR = 0x2A34,
UUID_HARDWARE_REVISION_STRING_CHAR = 0x2A27,
UUID_HEART_RATE_CONTROL_POINT_CHAR = 0x2A39,
UUID_HEART_RATE_MEASUREMENT_CHAR = 0x2A37,
UUID_HID_CONTROL_POINT_CHAR = 0x2A4C,
UUID_HID_INFORMATION_CHAR = 0x2A4A,
UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR = 0x2A2A,
UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR = 0x2A36,
UUID_INTERMEDIATE_TEMPERATURE_CHAR = 0x2A1E,
UUID_LOCAL_TIME_INFORMATION_CHAR = 0x2A0F,
UUID_MANUFACTURER_NAME_STRING_CHAR = 0x2A29,
UUID_MEASUREMENT_INTERVAL_CHAR = 0x2A21,
UUID_MODEL_NUMBER_STRING_CHAR = 0x2A24,
UUID_UNREAD_ALERT_CHAR = 0x2A45,
UUID_NEW_ALERT_CHAR = 0x2A46,
UUID_PNP_ID_CHAR = 0x2A50,
UUID_PROTOCOL_MODE_CHAR = 0x2A4E,
UUID_RECORD_ACCESS_CONTROL_POINT_CHAR = 0x2A52,
UUID_REFERENCE_TIME_INFORMATION_CHAR = 0x2A14,
UUID_REPORT_CHAR = 0x2A4D,
UUID_REPORT_MAP_CHAR = 0x2A4B,
UUID_RINGER_CONTROL_POINT_CHAR = 0x2A40,
UUID_RINGER_SETTING_CHAR = 0x2A41,
UUID_SCAN_INTERVAL_WINDOW_CHAR = 0x2A4F,
UUID_SCAN_REFRESH_CHAR = 0x2A31,
UUID_SERIAL_NUMBER_STRING_CHAR = 0x2A25,
UUID_SOFTWARE_REVISION_STRING_CHAR = 0x2A28,
UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR = 0x2A47,
UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR = 0x2A48,
UUID_SYSTEM_ID_CHAR = 0x2A23,
UUID_TEMPERATURE_MEASUREMENT_CHAR = 0x2A1C,
UUID_TEMPERATURE_TYPE_CHAR = 0x2A1D,
UUID_TIME_ACCURACY_CHAR = 0x2A12,
UUID_TIME_SOURCE_CHAR = 0x2A13,
UUID_TIME_UPDATE_CONTROL_POINT_CHAR = 0x2A16,
UUID_TIME_UPDATE_STATE_CHAR = 0x2A17,
UUID_TIME_WITH_DST_CHAR = 0x2A11,
UUID_TIME_ZONE_CHAR = 0x2A0E,
UUID_TX_POWER_LEVEL_CHAR = 0x2A07,
UUID_CSC_FEATURE_CHAR = 0x2A5C,
UUID_CSC_MEASUREMENT_CHAR = 0x2A5B,
UUID_RSC_FEATURE_CHAR = 0x2A54,
UUID_RSC_MEASUREMENT_CHAR = 0x2A53,
};
/**************************************************************************/
/*!
\brief Standard GATT characteristic presentation format unit types.
These unit types are used to decribe what the raw numeric
data in a characteristic actually represents.
\note See https://developer.bluetooth.org/gatt/units/Pages/default.aspx
*/
/**************************************************************************/
typedef enum ble_gatt_unit_e
{
BLE_GATT_UNIT_NONE = 0x2700, /**< No specified unit type */
BLE_GATT_UNIT_LENGTH_METRE = 0x2701, /**< Length, Metre */
BLE_GATT_UNIT_MASS_KILOGRAM = 0x2702, /**< Mass, Kilogram */
BLE_GATT_UNIT_TIME_SECOND = 0x2703, /**< Time, Second */
BLE_GATT_UNIT_ELECTRIC_CURRENT_AMPERE = 0x2704, /**< Electric Current, Ampere */
BLE_GATT_UNIT_THERMODYNAMIC_TEMPERATURE_KELVIN = 0x2705, /**< Thermodynamic Temperature, Kelvin */
BLE_GATT_UNIT_AMOUNT_OF_SUBSTANCE_MOLE = 0x2706, /**< Amount of Substance, Mole */
BLE_GATT_UNIT_LUMINOUS_INTENSITY_CANDELA = 0x2707, /**< Luminous Intensity, Candela */
BLE_GATT_UNIT_AREA_SQUARE_METRES = 0x2710, /**< Area, Square Metres */
BLE_GATT_UNIT_VOLUME_CUBIC_METRES = 0x2711, /**< Volume, Cubic Metres*/
BLE_GATT_UNIT_VELOCITY_METRES_PER_SECOND = 0x2712, /**< Velocity, Metres per Second*/
BLE_GATT_UNIT_ACCELERATION_METRES_PER_SECOND_SQUARED = 0x2713, /**< Acceleration, Metres per Second Squared */
BLE_GATT_UNIT_WAVENUMBER_RECIPROCAL_METRE = 0x2714, /**< Wave Number Reciprocal, Metre */
BLE_GATT_UNIT_DENSITY_KILOGRAM_PER_CUBIC_METRE = 0x2715, /**< Density, Kilogram per Cubic Metre */
BLE_GATT_UNIT_SURFACE_DENSITY_KILOGRAM_PER_SQUARE_METRE = 0x2716, /**< */
BLE_GATT_UNIT_SPECIFIC_VOLUME_CUBIC_METRE_PER_KILOGRAM = 0x2717, /**< */
BLE_GATT_UNIT_CURRENT_DENSITY_AMPERE_PER_SQUARE_METRE = 0x2718, /**< */
BLE_GATT_UNIT_MAGNETIC_FIELD_STRENGTH_AMPERE_PER_METRE = 0x2719, /**< Magnetic Field Strength, Ampere per Metre */
BLE_GATT_UNIT_AMOUNT_CONCENTRATION_MOLE_PER_CUBIC_METRE = 0x271A, /**< */
BLE_GATT_UNIT_MASS_CONCENTRATION_KILOGRAM_PER_CUBIC_METRE = 0x271B, /**< */
BLE_GATT_UNIT_LUMINANCE_CANDELA_PER_SQUARE_METRE = 0x271C, /**< */
BLE_GATT_UNIT_REFRACTIVE_INDEX = 0x271D, /**< */
BLE_GATT_UNIT_RELATIVE_PERMEABILITY = 0x271E, /**< */
BLE_GATT_UNIT_PLANE_ANGLE_RADIAN = 0x2720, /**< */
BLE_GATT_UNIT_SOLID_ANGLE_STERADIAN = 0x2721, /**< */
BLE_GATT_UNIT_FREQUENCY_HERTZ = 0x2722, /**< Frequency, Hertz */
BLE_GATT_UNIT_FORCE_NEWTON = 0x2723, /**< Force, Newton */
BLE_GATT_UNIT_PRESSURE_PASCAL = 0x2724, /**< Pressure, Pascal */
BLE_GATT_UNIT_ENERGY_JOULE = 0x2725, /**< Energy, Joule */
BLE_GATT_UNIT_POWER_WATT = 0x2726, /**< Power, Watt */
BLE_GATT_UNIT_ELECTRIC_CHARGE_COULOMB = 0x2727, /**< Electrical Charge, Coulomb */
BLE_GATT_UNIT_ELECTRIC_POTENTIAL_DIFFERENCE_VOLT = 0x2728, /**< Electrical Potential Difference, Voltage */
BLE_GATT_UNIT_CAPACITANCE_FARAD = 0x2729, /**< */
BLE_GATT_UNIT_ELECTRIC_RESISTANCE_OHM = 0x272A, /**< */
BLE_GATT_UNIT_ELECTRIC_CONDUCTANCE_SIEMENS = 0x272B, /**< */
BLE_GATT_UNIT_MAGNETIC_FLEX_WEBER = 0x272C, /**< */
BLE_GATT_UNIT_MAGNETIC_FLEX_DENSITY_TESLA = 0x272D, /**< */
BLE_GATT_UNIT_INDUCTANCE_HENRY = 0x272E, /**< */
BLE_GATT_UNIT_THERMODYNAMIC_TEMPERATURE_DEGREE_CELSIUS = 0x272F, /**< */
BLE_GATT_UNIT_LUMINOUS_FLUX_LUMEN = 0x2730, /**< */
BLE_GATT_UNIT_ILLUMINANCE_LUX = 0x2731, /**< */
BLE_GATT_UNIT_ACTIVITY_REFERRED_TO_A_RADIONUCLIDE_BECQUEREL = 0x2732, /**< */
BLE_GATT_UNIT_ABSORBED_DOSE_GRAY = 0x2733, /**< */
BLE_GATT_UNIT_DOSE_EQUIVALENT_SIEVERT = 0x2734, /**< */
BLE_GATT_UNIT_CATALYTIC_ACTIVITY_KATAL = 0x2735, /**< */
BLE_GATT_UNIT_DYNAMIC_VISCOSITY_PASCAL_SECOND = 0x2740, /**< */
BLE_GATT_UNIT_MOMENT_OF_FORCE_NEWTON_METRE = 0x2741, /**< */
BLE_GATT_UNIT_SURFACE_TENSION_NEWTON_PER_METRE = 0x2742, /**< */
BLE_GATT_UNIT_ANGULAR_VELOCITY_RADIAN_PER_SECOND = 0x2743, /**< */
BLE_GATT_UNIT_ANGULAR_ACCELERATION_RADIAN_PER_SECOND_SQUARED = 0x2744, /**< */
BLE_GATT_UNIT_HEAT_FLUX_DENSITY_WATT_PER_SQUARE_METRE = 0x2745, /**< */
BLE_GATT_UNIT_HEAT_CAPACITY_JOULE_PER_KELVIN = 0x2746, /**< */
BLE_GATT_UNIT_SPECIFIC_HEAT_CAPACITY_JOULE_PER_KILOGRAM_KELVIN = 0x2747, /**< */
BLE_GATT_UNIT_SPECIFIC_ENERGY_JOULE_PER_KILOGRAM = 0x2748, /**< */
BLE_GATT_UNIT_THERMAL_CONDUCTIVITY_WATT_PER_METRE_KELVIN = 0x2749, /**< */
BLE_GATT_UNIT_ENERGY_DENSITY_JOULE_PER_CUBIC_METRE = 0x274A, /**< */
BLE_GATT_UNIT_ELECTRIC_FIELD_STRENGTH_VOLT_PER_METRE = 0x274B, /**< */
BLE_GATT_UNIT_ELECTRIC_CHARGE_DENSITY_COULOMB_PER_CUBIC_METRE = 0x274C, /**< */
BLE_GATT_UNIT_SURFACE_CHARGE_DENSITY_COULOMB_PER_SQUARE_METRE = 0x274D, /**< */
BLE_GATT_UNIT_ELECTRIC_FLUX_DENSITY_COULOMB_PER_SQUARE_METRE = 0x274E, /**< */
BLE_GATT_UNIT_PERMITTIVITY_FARAD_PER_METRE = 0x274F, /**< */
BLE_GATT_UNIT_PERMEABILITY_HENRY_PER_METRE = 0x2750, /**< */
BLE_GATT_UNIT_MOLAR_ENERGY_JOULE_PER_MOLE = 0x2751, /**< */
BLE_GATT_UNIT_MOLAR_ENTROPY_JOULE_PER_MOLE_KELVIN = 0x2752, /**< */
BLE_GATT_UNIT_EXPOSURE_COULOMB_PER_KILOGRAM = 0x2753, /**< */
BLE_GATT_UNIT_ABSORBED_DOSE_RATE_GRAY_PER_SECOND = 0x2754, /**< */
BLE_GATT_UNIT_RADIANT_INTENSITY_WATT_PER_STERADIAN = 0x2755, /**< */
BLE_GATT_UNIT_RADIANCE_WATT_PER_SQUARE_METRE_STERADIAN = 0x2756, /**< */
BLE_GATT_UNIT_CATALYTIC_ACTIVITY_CONCENTRATION_KATAL_PER_CUBIC_METRE = 0x2757, /**< */
BLE_GATT_UNIT_TIME_MINUTE = 0x2760, /**< Time, Minute */
BLE_GATT_UNIT_TIME_HOUR = 0x2761, /**< Time, Hour */
BLE_GATT_UNIT_TIME_DAY = 0x2762, /**< Time, Day */
BLE_GATT_UNIT_PLANE_ANGLE_DEGREE = 0x2763, /**< */
BLE_GATT_UNIT_PLANE_ANGLE_MINUTE = 0x2764, /**< */
BLE_GATT_UNIT_PLANE_ANGLE_SECOND = 0x2765, /**< */
BLE_GATT_UNIT_AREA_HECTARE = 0x2766, /**< */
BLE_GATT_UNIT_VOLUME_LITRE = 0x2767, /**< */
BLE_GATT_UNIT_MASS_TONNE = 0x2768, /**< */
BLE_GATT_UNIT_PRESSURE_BAR = 0x2780, /**< Pressure, Bar */
BLE_GATT_UNIT_PRESSURE_MILLIMETRE_OF_MERCURY = 0x2781, /**< Pressure, Millimetre of Mercury */
BLE_GATT_UNIT_LENGTH_ANGSTROM = 0x2782, /**< */
BLE_GATT_UNIT_LENGTH_NAUTICAL_MILE = 0x2783, /**< */
BLE_GATT_UNIT_AREA_BARN = 0x2784, /**< */
BLE_GATT_UNIT_VELOCITY_KNOT = 0x2785, /**< */
BLE_GATT_UNIT_LOGARITHMIC_RADIO_QUANTITY_NEPER = 0x2786, /**< */
BLE_GATT_UNIT_LOGARITHMIC_RADIO_QUANTITY_BEL = 0x2787, /**< */
BLE_GATT_UNIT_LENGTH_YARD = 0x27A0, /**< Length, Yard */
BLE_GATT_UNIT_LENGTH_PARSEC = 0x27A1, /**< Length, Parsec */
BLE_GATT_UNIT_LENGTH_INCH = 0x27A2, /**< Length, Inch */
BLE_GATT_UNIT_LENGTH_FOOT = 0x27A3, /**< Length, Foot */
BLE_GATT_UNIT_LENGTH_MILE = 0x27A4, /**< Length, Mile */
BLE_GATT_UNIT_PRESSURE_POUND_FORCE_PER_SQUARE_INCH = 0x27A5, /**< */
BLE_GATT_UNIT_VELOCITY_KILOMETRE_PER_HOUR = 0x27A6, /**< Velocity, Kilometre per Hour */
BLE_GATT_UNIT_VELOCITY_MILE_PER_HOUR = 0x27A7, /**< Velocity, Mile per Hour */
BLE_GATT_UNIT_ANGULAR_VELOCITY_REVOLUTION_PER_MINUTE = 0x27A8, /**< Angular Velocity, Revolution per Minute */
BLE_GATT_UNIT_ENERGY_GRAM_CALORIE = 0x27A9, /**< Energy, Gram Calorie */
BLE_GATT_UNIT_ENERGY_KILOGRAM_CALORIE = 0x27AA, /**< Energy, Kilogram Calorie */
BLE_GATT_UNIT_ENERGY_KILOWATT_HOUR = 0x27AB, /**< Energy, Killowatt Hour */
BLE_GATT_UNIT_THERMODYNAMIC_TEMPERATURE_DEGREE_FAHRENHEIT = 0x27AC, /**< */
BLE_GATT_UNIT_PERCENTAGE = 0x27AD, /**< Percentage */
BLE_GATT_UNIT_PER_MILLE = 0x27AE, /**< */
BLE_GATT_UNIT_PERIOD_BEATS_PER_MINUTE = 0x27AF, /**< */
BLE_GATT_UNIT_ELECTRIC_CHARGE_AMPERE_HOURS = 0x27B0, /**< */
BLE_GATT_UNIT_MASS_DENSITY_MILLIGRAM_PER_DECILITRE = 0x27B1, /**< */
BLE_GATT_UNIT_MASS_DENSITY_MILLIMOLE_PER_LITRE = 0x27B2, /**< */
BLE_GATT_UNIT_TIME_YEAR = 0x27B3, /**< Time, Year */
BLE_GATT_UNIT_TIME_MONTH = 0x27B4, /**< Time, Month */
BLE_GATT_UNIT_CONCENTRATION_COUNT_PER_CUBIC_METRE = 0x27B5, /**< */
BLE_GATT_UNIT_IRRADIANCE_WATT_PER_SQUARE_METRE = 0x27B6 /**< */
} ble_gatt_unit_t;
/**************************************************************************/
/*!
\brief Standard GATT number types
\note See Bluetooth Specification 4.0 (Vol. 3), Part G, Section 3.3.3.5.2
\note See http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
*/
/**************************************************************************/
typedef enum ble_gatt_format_e
{
BLE_GATT_FORMAT_RFU = 0x00, /**< Reserved For Future Use. */
BLE_GATT_FORMAT_BOOLEAN = 0x01, /**< Boolean. */
BLE_GATT_FORMAT_2BIT = 0x02, /**< Unsigned 2-bit integer. */
BLE_GATT_FORMAT_NIBBLE = 0x03, /**< Unsigned 4-bit integer. */
BLE_GATT_FORMAT_UINT8 = 0x04, /**< Unsigned 8-bit integer. */
BLE_GATT_FORMAT_UINT12 = 0x05, /**< Unsigned 12-bit integer. */
BLE_GATT_FORMAT_UINT16 = 0x06, /**< Unsigned 16-bit integer. */
BLE_GATT_FORMAT_UINT24 = 0x07, /**< Unsigned 24-bit integer. */
BLE_GATT_FORMAT_UINT32 = 0x08, /**< Unsigned 32-bit integer. */
BLE_GATT_FORMAT_UINT48 = 0x09, /**< Unsigned 48-bit integer. */
BLE_GATT_FORMAT_UINT64 = 0x0A, /**< Unsigned 64-bit integer. */
BLE_GATT_FORMAT_UINT128 = 0x0B, /**< Unsigned 128-bit integer. */
BLE_GATT_FORMAT_SINT8 = 0x0C, /**< Signed 2-bit integer. */
BLE_GATT_FORMAT_SINT12 = 0x0D, /**< Signed 12-bit integer. */
BLE_GATT_FORMAT_SINT16 = 0x0E, /**< Signed 16-bit integer. */
BLE_GATT_FORMAT_SINT24 = 0x0F, /**< Signed 24-bit integer. */
BLE_GATT_FORMAT_SINT32 = 0x10, /**< Signed 32-bit integer. */
BLE_GATT_FORMAT_SINT48 = 0x11, /**< Signed 48-bit integer. */
BLE_GATT_FORMAT_SINT64 = 0x12, /**< Signed 64-bit integer. */
BLE_GATT_FORMAT_SINT128 = 0x13, /**< Signed 128-bit integer. */
BLE_GATT_FORMAT_FLOAT32 = 0x14, /**< IEEE-754 32-bit floating point. */
BLE_GATT_FORMAT_FLOAT64 = 0x15, /**< IEEE-754 64-bit floating point. */
BLE_GATT_FORMAT_SFLOAT = 0x16, /**< IEEE-11073 16-bit SFLOAT. */
BLE_GATT_FORMAT_FLOAT = 0x17, /**< IEEE-11073 32-bit FLOAT. */
BLE_GATT_FORMAT_DUINT16 = 0x18, /**< IEEE-20601 format. */
BLE_GATT_FORMAT_UTF8S = 0x19, /**< UTF-8 string. */
BLE_GATT_FORMAT_UTF16S = 0x1A, /**< UTF-16 string. */
BLE_GATT_FORMAT_STRUCT = 0x1B /**< Opaque Structure. */
} ble_gatt_format_t;
/**************************************************************************/
/*!
\brief Standard GATT characteritic properties
\note See Bluetooth Specification 4.0 (Vol. 3), Part G, Section 3.3.1.1
and Section 3.3.3.1 for Extended Properties
*/
/**************************************************************************/
typedef enum ble_gatt_char_properties_e
{
BLE_GATT_CHAR_PROPERTIES_BROADCAST = 0x01, /**< Permits broadcasts of the Characteristic Value using Server Characteristic Configuration Descriptor. */
BLE_GATT_CHAR_PROPERTIES_READ = 0x02, /**< Permits reads of the Characteristic Value. */
BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE = 0x04, /**< Permits writes of the Characteristic Value without response. */
BLE_GATT_CHAR_PROPERTIES_WRITE = 0x08, /**< Permits writes of the Characteristic Value with response. */
BLE_GATT_CHAR_PROPERTIES_NOTIFY = 0x10, /**< Permits notifications of a Characteristic Value without acknowledgement. */
BLE_GATT_CHAR_PROPERTIES_INDICATE = 0x20, /**< Permits indications of a Characteristic Value with acknowledgement. */
BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES = 0x40, /**< Permits signed writes to the Characteristic Value. */
BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES = 0x80 /**< Additional characteristic properties are defined in the Characteristic Extended Properties Descriptor */
} ble_gatt_char_properties_t;
/**************************************************************************/
/*!
\brief GATT presentation format wrapper
\note See Bluetooth Specification 4.0 (Vol. 3), Part G, Section 3.3.3.5
\note See https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
*/
/**************************************************************************/
typedef struct PresentationFormat
{
uint8_t gatt_format; /**< Format of the value, see @ref ble_gatt_format_t. */
int8_t exponent; /**< Exponent for integer data types. Ex. if Exponent = -3 and the char value is 3892, the actual value is 3.892 */
uint16_t gatt_unit; /**< UUID from Bluetooth Assigned Numbers, see @ref ble_gatt_unit_t. */
uint8_t gatt_namespace; /**< Namespace from Bluetooth Assigned Numbers, normally '1', see @ref BLE_GATT_CPF_NAMESPACES. */
uint16_t gatt_nsdesc; /**< Namespace description from Bluetooth Assigned Numbers, normally '0', see @ref BLE_GATT_CPF_NAMESPACES. */
} presentation_format_t;
GattCharacteristic(uint16_t uuid=0, uint16_t minLen=1, uint16_t maxLen=1, uint8_t properties=0);
virtual ~GattCharacteristic(void);
uint16_t uuid; /* Characteristic UUID */
uint16_t lenMin; /* Minimum length of the value */
uint16_t lenMax; /* Maximum length of the value */
uint16_t handle;
uint8_t properties;
private:
};
#endif

View File

@ -1,111 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 <stdio.h>
#include <string.h>
#include "GattService.h"
/**************************************************************************/
/*!
@brief Creates a new GattService using the specified 128-bit UUID
@note The UUID value must be unique on the device
@param[in] uuid
The 16 byte (128-bit) UUID to use for this characteristic
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
GattService::GattService(uint8_t base_uuid[16])
{
primaryServiceID.update(base_uuid);
characteristicCount = 0;
handle = 0;
}
/**************************************************************************/
/*!
@brief Creates a new GattService using the specified 16-bit BLE UUID
@param[in] ble_uuid
The standardised 16-bit (2 byte) BLE UUID to use for this
characteristic
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
GattService::GattService(uint16_t ble_uuid)
{
primaryServiceID.update( ble_uuid );
characteristicCount = 0;
handle = 0;
}
/**************************************************************************/
/*!
@brief Destructor
*/
/**************************************************************************/
GattService::~GattService(void)
{
}
/**************************************************************************/
/*!
@brief Adds a GattCharacterisic to the service.
@note This function will not update the .handle field in the
GattCharacteristic. This value is updated when the parent
service is added via the radio driver.
@param[in] characteristic
The GattCharacteristic object describing the characteristic
to add to this service
@returns BLE_ERROR_NONE (0) if everything executed correctly, or an
error code if there was a problem
@retval BLE_ERROR_NONE
Everything executed correctly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t GattService::addCharacteristic(GattCharacteristic & characteristic)
{
/* ToDo: Make sure we don't overflow the array, etc. */
/* ToDo: Make sure this characteristic UUID doesn't already exist */
/* ToDo: Basic validation */
characteristics[characteristicCount] = &characteristic;
characteristicCount++;
return BLE_ERROR_NONE;
}

View File

@ -1,70 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __GATT_SERVICE_H__
#define __GATT_SERVICE_H__
#include "blecommon.h"
#include "UUID.h"
#include "GattCharacteristic.h"
#define BLE_SERVICE_MAX_CHARACTERISTICS (5)
/**************************************************************************/
/*!
\brief GATT service
*/
/**************************************************************************/
class GattService
{
private:
public:
GattService(uint8_t[16]); /* 128-bit Base UUID */
GattService(uint16_t); /* 16-bit BLE UUID */
virtual ~GattService(void);
UUID primaryServiceID;
uint8_t characteristicCount;
GattCharacteristic* characteristics[BLE_SERVICE_MAX_CHARACTERISTICS];
uint16_t handle;
ble_error_t addCharacteristic(GattCharacteristic &);
enum {
UUID_ALERT_NOTIFICATION_SERVICE = 0x1811,
UUID_BATTERY_SERVICE = 0x180F,
UUID_BLOOD_PRESSURE_SERVICE = 0x1810,
UUID_CURRENT_TIME_SERVICE = 0x1805,
UUID_CYCLING_SPEED_AND_CADENCE = 0x1816,
UUID_DEVICE_INFORMATION_SERVICE = 0x180A,
UUID_GLUCOSE_SERVICE = 0x1808,
UUID_HEALTH_THERMOMETER_SERVICE = 0x1809,
UUID_HEART_RATE_SERVICE = 0x180D,
UUID_HUMAN_INTERFACE_DEVICE_SERVICE = 0x1812,
UUID_IMMEDIATE_ALERT_SERVICE = 0x1802,
UUID_LINK_LOSS_SERVICE = 0x1803,
UUID_NEXT_DST_CHANGE_SERVICE = 0x1807,
UUID_PHONE_ALERT_STATUS_SERVICE = 0x180E,
UUID_REFERENCE_TIME_UPDATE_SERVICE = 0x1806,
UUID_RUNNING_SPEED_AND_CADENCE = 0x1814,
UUID_SCAN_PARAMETERS_SERVICE = 0x1813,
UUID_TX_POWER_SERVICE = 0x1804
};
};
#endif

View File

@ -1,194 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 <stdio.h>
#include <string.h>
#include "UUID.h"
/**************************************************************************/
/*!
@brief Creates an empty 128-bit UUID
@note This UUID must be assigned a valid value via the 'update'
function before it can be safely used!
*/
/**************************************************************************/
UUID::UUID(void)
{
memset(base, 0, 16);
value = 0;
type = UUID_TYPE_SHORT;
}
/**************************************************************************/
/*!
@brief Creates a new 128-bit UUID
@note The UUID is a unique 128-bit (16 byte) ID used to identify
different service or characteristics on the BLE device.
@note When creating a UUID, the constructor will check if all bytes
except bytes 2/3 are equal to 0. If only bytes 2/3 have a
value, the UUID will be treated as a short/BLE UUID, and the
.type field will be set to UUID::UUID_TYPE_SHORT. If any
of the bytes outside byte 2/3 have a non-zero value, the UUID
will be considered a 128-bit ID, and .type will be assigned
as UUID::UUID_TYPE_LONG.
@param[in] uuid_base
The 128-bit (16-byte) UUID value. For 128-bit values,
assign all 16 bytes. For 16-bit values, assign the
16-bits to byte 2 and 3, and leave the rest of the bytes
as 0.
@section EXAMPLE
@code
// Create a short UUID (0x180F)
uint8_t shortID[16] = { 0, 0, 0x0F, 0x18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
UUID ble_uuid = UUID(shortID);
// ble_uuid.type = UUID_TYPE_SHORT
// ble_uuid.value = 0x180F
// Creeate a long UUID
uint8_t longID[16] = { 0x00, 0x11, 0x22, 0x33,
0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB,
0xCC, 0xDD, 0xEE, 0xFF };
UUID custom_uuid = UUID(longID);
// custom_uuid.type = UUID_TYPE_LONG
// custom_uuid.value = 0x3322
// custom_uuid.base = 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
@endcode
*/
/**************************************************************************/
UUID::UUID(uint8_t const uuid_base[16])
{
memcpy(base, uuid_base, 16);
value = (uint16_t)((uuid_base[3] << 8) | (uuid_base[2]));
/* Check if this is a short of a long UUID */
if (uuid_base[0] + uuid_base[1] +
uuid_base[4] + uuid_base[5] + uuid_base[6] + uuid_base[7] +
uuid_base[8] + uuid_base[9] + uuid_base[10] + uuid_base[11] +
uuid_base[12] + uuid_base[13] + uuid_base[14] + uuid_base[15] == 0)
{
type = UUID_TYPE_SHORT;
}
else
{
type = UUID_TYPE_LONG;
}
}
/**************************************************************************/
/*!
@brief Creates a short (16-bit) UUID
@param[in] ble_uuid
The 16-bit BLE UUID value.
*/
/**************************************************************************/
UUID::UUID(uint16_t const ble_uuid)
{
memset(base, 0, 16);
memcpy(base+2, (uint8_t *)&ble_uuid, 2);
value = ble_uuid;
type = UUID_TYPE_SHORT;
}
/**************************************************************************/
/*!
@brief UUID destructor
*/
/**************************************************************************/
UUID::~UUID(void)
{
}
/**************************************************************************/
/*!
@brief Updates the value of the UUID
@args[in] uuid_base
The 128-bit value to use when updating the UUID. For
16-bit IDs, insert the ID in bytes 2/3 in LSB format.
@returns BLE_ERROR_NONE (0) if everything executed correctly, or an
error code if there was a problem
@retval BLE_ERROR_NONE
Everything executed correctly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t UUID::update(uint8_t const uuid_base[16])
{
memcpy(base, uuid_base, 16);
value = (uint16_t)((uuid_base[3] << 8) | (uuid_base[2]));
/* Check if this is a short of a long UUID */
if (uuid_base[0] + uuid_base[1] +
uuid_base[4] + uuid_base[5] + uuid_base[6] + uuid_base[7] +
uuid_base[8] + uuid_base[9] + uuid_base[10] + uuid_base[11] +
uuid_base[12] + uuid_base[13] + uuid_base[14] + uuid_base[15] == 0)
{
type = UUID_TYPE_SHORT;
}
else
{
type = UUID_TYPE_LONG;
}
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Updates the value of the UUID
@args[in] ble_uuid
The 16-bit value to use when updating the UUID.
@returns BLE_ERROR_NONE (0) if everything executed correctly, or an
error code if there was a problem
@retval BLE_ERROR_NONE
Everything executed correctly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t UUID::update(uint16_t const ble_uuid)
{
memset(base, 0, 16);
memcpy(base+2, (uint8_t *)&ble_uuid, 2);
value = ble_uuid;
type = UUID_TYPE_SHORT;
return BLE_ERROR_NONE;
}

View File

@ -1,47 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __UUID_H__
#define __UUID_H__
#include "blecommon.h"
class UUID
{
private:
public:
enum
{
UUID_TYPE_SHORT = 0, // Short BLE UUID
UUID_TYPE_LONG = 1 // Full 128-bit UUID
};
UUID(void);
UUID(uint8_t const[16]);
UUID(uint16_t const);
virtual ~UUID(void);
uint8_t type; // UUID_TYPE_SHORT or UUID_TYPE_LONG
uint8_t base[16]; // in case of custom
uint16_t value; // 16 bit uuid (byte 2-3 using with base)
ble_error_t update(uint8_t const[16]);
ble_error_t update(uint16_t const);
};
#endif

View File

@ -1,48 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __BLE_COMMON_H__
#define __BLE_COMMON_H__
#define NRF51
#define DEBUG_NRF_USER
#define BLE_STACK_SUPPORT_REQD
#define BOARD_PCA10001
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/**************************************************************************/
/*!
\brief Error codes for the BLE API
*/
/**************************************************************************/
typedef enum ble_error_e
{
BLE_ERROR_NONE = 0, /**< No error */
BLE_ERROR_BUFFER_OVERFLOW = 1, /**< The requested action would cause a buffer overflow and has been aborted */
BLE_ERROR_NOT_IMPLEMENTED = 2, /**< Requested a feature that isn't yet implement or isn't supported by the target HW */
BLE_ERROR_PARAM_OUT_OF_RANGE = 3 /**< One of the supplied parameters is outside the valid range */
} ble_error_t;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,41 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __BLE_DEVICE_H__
#define __BLE_DEVICE_H__
#include "mbed.h"
#include "blecommon.h"
#include "hw/Gap.h"
#include "hw/GattServer.h"
/**************************************************************************/
/*!
\brief
The base class used to abstract away BLE capable radio transceivers
or SOCs, to enable this BLE API to work with any radio transparently.
*/
/**************************************************************************/
class BLEDevice
{
public:
virtual Gap& getGap() = 0;
virtual GattServer& getGattServer() = 0;
virtual ble_error_t init() = 0;
virtual ble_error_t reset(void) = 0;
};
#endif

View File

@ -1,84 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __GAP_H__
#define __GAP_H__
#include "mbed.h"
#include "blecommon.h"
#include "GapAdvertisingData.h"
#include "GapAdvertisingParams.h"
#include "GapEvents.h"
/**************************************************************************/
/*!
\brief
The base class used to abstract GAP functionality to a specific radio
transceiver, SOC or BLE Stack.
*/
/**************************************************************************/
class Gap
{
private:
GapEvents *m_pEventHandler;
public:
typedef enum addr_type_e{
ADDR_TYPE_PUBLIC = 0,
ADDR_TYPE_RANDOM_STATIC,
ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE,
ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
} addr_type_t;
/* These functions must be defined in the sub-class */
virtual ble_error_t setAddress(addr_type_t type, uint8_t address[6]) = 0;
virtual ble_error_t setAdvertisingData(GapAdvertisingData &, GapAdvertisingData &) = 0;
virtual ble_error_t startAdvertising(GapAdvertisingParams &) = 0;
virtual ble_error_t stopAdvertising(void) = 0;
virtual ble_error_t disconnect(void) = 0;
/* Describes the current state of the device (more than one bit can be set) */
typedef struct GapState_s
{
unsigned advertising : 1; /**< The device is current advertising */
unsigned connected : 1; /**< The peripheral is connected to a central device */
} GapState_t;
/* Event callback handlers */
void setEventHandler(GapEvents *pEventHandler) {m_pEventHandler = pEventHandler;}
void handleEvent(GapEvents::gapEvent_e type) {
if (NULL == m_pEventHandler)
return;
switch(type) {
case GapEvents::GAP_EVENT_TIMEOUT:
state.advertising = 0;
m_pEventHandler->onTimeout();
break;
case GapEvents::GAP_EVENT_CONNECTED:
state.connected = 1;
m_pEventHandler->onConnected();
break;
case GapEvents::GAP_EVENT_DISCONNECTED:
state.connected = 0;
m_pEventHandler->onDisconnected();
break;
}
}
GapState_t state;
};
#endif

View File

@ -1,71 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __GAP_EVENTS_H__
#define __GAP_EVENTS_H__
#include "blecommon.h"
#include "mbed.h"
/**************************************************************************/
/*!
\brief
The base class used to abstract away the callback events that can be
triggered with the GAP.
*/
/**************************************************************************/
class GapEvents {
public:
/******************************************************************/
/*!
\brief
Identifies GAP events generated by the radio HW when an event
callback occurs
*/
/******************************************************************/
typedef enum gapEvent_e
{
GAP_EVENT_TIMEOUT = 1, /**< Advertising timed out before a connection was established */
GAP_EVENT_CONNECTED = 2, /**< A connection was established with a central device */
GAP_EVENT_DISCONNECTED = 3 /**< A connection was closed or lost with a central device */
} gapEvent_t;
/******************************************************************/
/*!
\brief
Advertising timed out before a connection was established
*/
/******************************************************************/
virtual void onTimeout(void) {}
/******************************************************************/
/*!
\brief
A connection was established with a central device
*/
/******************************************************************/
virtual void onConnected(void) {}
/******************************************************************/
/*!
\brief
A connection was closed or lost with a central device
*/
/******************************************************************/
virtual void onDisconnected(void) {}
};
#endif

View File

@ -1,76 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __GATT_SERVER_H__
#define __GATT_SERVER_H__
#include "mbed.h"
#include "blecommon.h"
#include "GattService.h"
#include "GattServerEvents.h"
/**************************************************************************/
/*!
\brief
The base class used to abstract GATT Server functionality to a specific
radio transceiver, SOC or BLE Stack.
*/
/**************************************************************************/
class GattServer
{
private:
GattServerEvents *m_pEventHandler;
public:
/* These functions must be defined in the sub-class */
virtual ble_error_t addService(GattService &) = 0;
virtual ble_error_t readValue(uint16_t, uint8_t[], uint16_t) = 0;
virtual ble_error_t updateValue(uint16_t, uint8_t[], uint16_t, bool localOnly = false) = 0;
// ToDo: For updateValue, check the CCCD to see if the value we are
// updating has the notify or indicate bits sent, and if BOTH are set
// be sure to call sd_ble_gatts_hvx() twice with notify then indicate!
// Strange use case, but valid and must be covered!
/* Event callback handlers */
void setEventHandler(GattServerEvents *pEventHandler) {m_pEventHandler = pEventHandler;}
void handleEvent(GattServerEvents::gattEvent_e type, uint16_t charHandle) {
if (NULL == m_pEventHandler)
return;
switch(type) {
case GattServerEvents::GATT_EVENT_DATA_SENT:
m_pEventHandler->onDataSent(charHandle);
break;
case GattServerEvents::GATT_EVENT_DATA_WRITTEN:
m_pEventHandler->onDataWritten(charHandle);
break;
case GattServerEvents::GATT_EVENT_UPDATES_ENABLED:
m_pEventHandler->onUpdatesEnabled(charHandle);
break;
case GattServerEvents::GATT_EVENT_UPDATES_DISABLED:
m_pEventHandler->onUpdatesDisabled(charHandle);
break;
case GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED:
m_pEventHandler->onConfirmationReceived(charHandle);
break;
}
}
uint8_t serviceCount;
uint8_t characteristicCount;
};
#endif

View File

@ -1,91 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __GATT_SERVER_EVENTS_H__
#define __GATT_SERVER_EVENTS_H__
#include "blecommon.h"
#include "mbed.h"
/**************************************************************************/
/*!
\brief
The base class used to abstract away the callback events that can be
triggered with the GATT Server.
*/
/**************************************************************************/
class GattServerEvents {
public:
/******************************************************************/
/*!
\brief
Identifies GATT events generated by the radio HW when an event
callback occurs
*/
/******************************************************************/
typedef enum gattEvent_e
{
GATT_EVENT_DATA_SENT = 1, /**< Fired when a msg was successfully sent out (notify only?) */
GATT_EVENT_DATA_WRITTEN = 2, /**< Client wrote data to Server (separate into char and descriptor writes?) */
GATT_EVENT_UPDATES_ENABLED = 3, /**< Notify/Indicate Enabled in CCCD */
GATT_EVENT_UPDATES_DISABLED = 4, /**< Notify/Indicate Disabled in CCCD */
GATT_EVENT_CONFIRMATION_RECEIVED = 5 /**< Response received from Indicate message */
} gattEvent_t;
/******************************************************************/
/*!
\brief
A message was successfully transmitted
*/
/******************************************************************/
virtual void onDataSent(uint16_t charHandle) {}
/******************************************************************/
/*!
\brief
The GATT client (the phone, tablet, etc.) wrote data to a
characteristic or descriptor on the GATT Server (the peripheral
device).
*/
/******************************************************************/
virtual void onDataWritten(uint16_t charHandle) {}
/******************************************************************/
/*!
\brief
A Notify or Indicate flag was enabled in the CCCD
*/
/******************************************************************/
virtual void onUpdatesEnabled(uint16_t charHandle) {}
/******************************************************************/
/*!
\brief
A Notify or Indicate flag was disabled in the CCCD
*/
/******************************************************************/
virtual void onUpdatesDisabled(uint16_t charHandle) {}
/******************************************************************/
/*!
\brief
A confirmation response was received from an Indicate message
*/
/******************************************************************/
virtual void onConfirmationReceived(uint16_t charHandle) {}
};
#endif

View File

@ -1,220 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 "common/common.h"
#include "app_timer.h"
#include "btle.h"
#include "ble_stack_handler_types.h"
#include "ble_radio_notification.h"
#include "ble_flash.h"
#include "ble_bondmngr.h"
#include "ble_conn_params.h"
#include "btle_gap.h"
#include "btle_advertising.h"
#include "custom/custom_helper.h"
#include "nordic_common.h"
#include "softdevice_handler.h"
#include "pstorage.h"
#include "hw/GapEvents.h"
#include "nRF51Gap.h"
#include "nRF51GattServer.h"
static void service_error_callback(uint32_t nrf_error);
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name);
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name);
static error_t bond_manager_init(void);
static void btle_handler(ble_evt_t * p_ble_evt);
/**************************************************************************/
/*!
*/
/**************************************************************************/
static void sys_evt_dispatch(uint32_t sys_evt)
{
pstorage_sys_event_handler(sys_evt);
}
/**************************************************************************/
/*!
@brief Initialises BTLE and the underlying HW/SoftDevice
@returns
*/
/**************************************************************************/
error_t btle_init(void)
{
APP_TIMER_INIT(0, 8, 5, false);
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler) );
ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch) );
bond_manager_init();
btle_gap_init();
return ERROR_NONE;
}
/**************************************************************************/
/*!
@brief
@param[in] p_ble_evt
@returns
*/
/**************************************************************************/
static void btle_handler(ble_evt_t * p_ble_evt)
{
/* Library service handlers */
ble_bondmngr_on_ble_evt(p_ble_evt);
ble_conn_params_on_ble_evt(p_ble_evt);
/* Custom event handler */
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
nRF51Gap::getInstance().setConnectionHandle( p_ble_evt->evt.gap_evt.conn_handle );
nRF51Gap::getInstance().handleEvent(GapEvents::GAP_EVENT_CONNECTED);
break;
case BLE_GAP_EVT_DISCONNECTED:
// Since we are not in a connection and have not started advertising, store bonds
nRF51Gap::getInstance().setConnectionHandle (BLE_CONN_HANDLE_INVALID);
ASSERT_STATUS_RET_VOID ( ble_bondmngr_bonded_centrals_store() );
nRF51Gap::getInstance().handleEvent(GapEvents::GAP_EVENT_DISCONNECTED);
break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
{
ble_gap_sec_params_t sec_params = { 0 };
sec_params.timeout = 30 ; /**< Timeout for Pairing Request or Security Request (in seconds). */
sec_params.bond = 1 ; /**< Perform bonding. */
sec_params.mitm = CFG_BLE_SEC_PARAM_MITM ;
sec_params.io_caps = CFG_BLE_SEC_PARAM_IO_CAPABILITIES ;
sec_params.oob = CFG_BLE_SEC_PARAM_OOB ;
sec_params.min_key_size = CFG_BLE_SEC_PARAM_MIN_KEY_SIZE ;
sec_params.max_key_size = CFG_BLE_SEC_PARAM_MAX_KEY_SIZE ;
ASSERT_STATUS_RET_VOID ( sd_ble_gap_sec_params_reply(nRF51Gap::getInstance().getConnectionHandle(), BLE_GAP_SEC_STATUS_SUCCESS, &sec_params) );
}
break;
case BLE_GAP_EVT_TIMEOUT:
if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
{
nRF51Gap::getInstance().handleEvent(GapEvents::GAP_EVENT_TIMEOUT);
}
break;
case BLE_GATTC_EVT_TIMEOUT:
case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server and Client timeout events.
// ASSERT_STATUS_RET_VOID (sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
break;
default:
break;
}
nRF51GattServer::getInstance().hwCallback(p_ble_evt);
}
/**************************************************************************/
/*!
@brief Initialises the bond manager
@note Bond data will be cleared on reset if the bond delete
button is pressed during initialisation (the button is
defined as CFG_BLE_BOND_DELETE_BUTTON_NUM).
@returns
*/
/**************************************************************************/
static error_t bond_manager_init(void)
{
ble_bondmngr_init_t bond_para = { 0 };
ASSERT_STATUS ( pstorage_init() );
bond_para.flash_page_num_bond = CFG_BLE_BOND_FLASH_PAGE_BOND ;
bond_para.flash_page_num_sys_attr = CFG_BLE_BOND_FLASH_PAGE_SYS_ATTR ;
//bond_para.bonds_delete = boardButtonCheck(CFG_BLE_BOND_DELETE_BUTTON_NUM) ;
bond_para.evt_handler = NULL ;
bond_para.error_handler = service_error_callback ;
ASSERT_STATUS( ble_bondmngr_init( &bond_para ) );
/* Init radio active/inactive notification to flash (to only perform flashing when the radio is inactive) */
// ASSERT_STATUS( ble_radio_notification_init(NRF_APP_PRIORITY_HIGH,
// NRF_RADIO_NOTIFICATION_DISTANCE_4560US,
// ble_flash_on_radio_active_evt) );
return ERROR_NONE;
}
/**************************************************************************/
/*!
@brief
@param[in] nrf_error
@returns
*/
/**************************************************************************/
static void service_error_callback(uint32_t nrf_error)
{
ASSERT_STATUS_RET_VOID( nrf_error );
}
/**************************************************************************/
/*!
@brief Callback when an error occurs inside the SoftDevice
@param[in] line_num
@param[in] p-file_name
@returns
*/
/**************************************************************************/
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
ASSERT(false, (void) 0);
}
/**************************************************************************/
/*!
@brief Handler for general errors above the SoftDevice layer.
Typically we can' recover from this so we do a reset.
@param[in] error_code
@param[in] line_num
@param[in] p-file_name
@returns
*/
/**************************************************************************/
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
ASSERT_STATUS_RET_VOID( error_code );
NVIC_SystemReset();
}

View File

@ -1,35 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 _BTLE_H_
#define _BTLE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "common/common.h"
#include "ble_srv_common.h"
#include "ble.h"
error_t btle_init(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,43 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 "common/common.h"
#include "ble_advdata.h"
#include "btle.h"
/**************************************************************************/
/*!
@brief Starts the advertising process
@returns
*/
/**************************************************************************/
error_t btle_advertising_start(void)
{
ble_gap_adv_params_t adv_para = { 0 };
/* Set the default advertising parameters */
adv_para.type = BLE_GAP_ADV_TYPE_ADV_IND ;
adv_para.p_peer_addr = NULL ; /* Undirected advertising */
adv_para.fp = BLE_GAP_ADV_FP_ANY ;
adv_para.p_whitelist = NULL ;
adv_para.interval = (CFG_GAP_ADV_INTERVAL_MS*8)/5 ; /* Advertising interval in units of 0.625 ms */
adv_para.timeout = CFG_GAP_ADV_TIMEOUT_S ;
ASSERT_STATUS( sd_ble_gap_adv_start(&adv_para) );
return ERROR_NONE;
}

View File

@ -1,24 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 _BTLE_ADVERTISING_H_
#define _BTLE_ADVERTISING_H_
#include "common/common.h"
error_t btle_advertising_start(void);
#endif

View File

@ -1,90 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 "common/common.h"
#include "app_timer.h"
#include "ble_gap.h"
#include "ble_conn_params.h"
static inline uint32_t msec_to_1_25msec(uint32_t interval_ms) ATTR_ALWAYS_INLINE ATTR_CONST;
static void error_callback(uint32_t nrf_error);
/**************************************************************************/
/*!
@brief Initialise GAP in the underlying SoftDevice
@returns
*/
/**************************************************************************/
error_t btle_gap_init(void)
{
ble_gap_conn_params_t gap_conn_params = { 0 };
gap_conn_params.min_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MIN_INTERVAL_MS) ; // in 1.25ms unit
gap_conn_params.max_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MAX_INTERVAL_MS) ; // in 1.25ms unit
gap_conn_params.slave_latency = CFG_GAP_CONNECTION_SLAVE_LATENCY ;
gap_conn_params.conn_sup_timeout = CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS / 10 ; // in 10ms unit
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed
ASSERT_STATUS( sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *) CFG_GAP_LOCAL_NAME, strlen(CFG_GAP_LOCAL_NAME)) );
ASSERT_STATUS( sd_ble_gap_appearance_set(CFG_GAP_APPEARANCE) );
ASSERT_STATUS( sd_ble_gap_ppcp_set(&gap_conn_params) );
ASSERT_STATUS( sd_ble_gap_tx_power_set(CFG_BLE_TX_POWER_LEVEL) );
/* Connection Parameters */
enum {
FIRST_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER),
NEXT_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER),
MAX_UPDATE_COUNT = 3
};
ble_conn_params_init_t cp_init = { 0 };
cp_init.p_conn_params = NULL ;
cp_init.first_conn_params_update_delay = FIRST_UPDATE_DELAY ;
cp_init.next_conn_params_update_delay = NEXT_UPDATE_DELAY ;
cp_init.max_conn_params_update_count = MAX_UPDATE_COUNT ;
cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID ;
cp_init.disconnect_on_fail = true ;
cp_init.evt_handler = NULL ;
cp_init.error_handler = error_callback;
ASSERT_STATUS ( ble_conn_params_init(&cp_init) );
return ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Converts msecs to an integer representing 1.25ms units
@param[in] ms
The number of milliseconds to conver to 1.25ms units
@returns The number of 1.25ms units in the supplied number of ms
*/
/**************************************************************************/
static inline uint32_t msec_to_1_25msec(uint32_t interval_ms)
{
return (interval_ms * 4) / 5 ;
}
static void error_callback(uint32_t nrf_error)
{
ASSERT_STATUS_RET_VOID( nrf_error );
}

View File

@ -1,24 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 _BTLE_GAP_H_
#define _BTLE_GAP_H_
#include "common/common.h"
error_t btle_gap_init(void);
#endif

View File

@ -1,163 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 "custom_helper.h"
/**************************************************************************/
/*!
@brief Adds the base UUID to the custom service. All UUIDs used
by this service are based on this 128-bit UUID.
@note This UUID needs to be added to the SoftDevice stack before
adding the service's primary service via
'sd_ble_gatts_service_add'
@param[in] p_uuid_base A pointer to the 128-bit UUID array (8*16)
@returns The UUID type.
A return value of 0 should be considered an error.
@retval 0x00 BLE_UUID_TYPE_UNKNOWN
@retval 0x01 BLE_UUID_TYPE_BLE
@retval 0x02 BLE_UUID_TYPE_VENDOR_BEGIN
@section EXAMPLE
@code
// Take note that bytes 2/3 are blank since these are used to identify
// the primary service and individual characteristics
#define CFG_CUSTOM_UUID_BASE "\x6E\x40\x00\x00\xB5\xA3\xF3\x93\xE0\xA9\xE5\x0E\x24\xDC\xCA\x9E"
uint8_t uuid_type = custom_add_uuid_base(CFG_CUSTOM_UUID_BASE);
ASSERT(uuid_type > 0, ERROR_NOT_FOUND);
// We can now safely add the primary service and any characteristics
// for our custom service ...
@endcode
*/
/**************************************************************************/
uint8_t custom_add_uuid_base(uint8_t const * const p_uuid_base)
{
ble_uuid128_t base_uuid;
uint8_t uuid_type = 0;
/* Reverse the bytes since ble_uuid128_t is LSB */
for(uint8_t i=0; i<16; i++)
{
base_uuid.uuid128[i] = p_uuid_base[15-i];
}
ASSERT_INT( ERROR_NONE, sd_ble_uuid_vs_add( &base_uuid, &uuid_type ), 0);
return uuid_type;
}
/**************************************************************************/
/*!
*/
/**************************************************************************/
error_t custom_decode_uuid_base(uint8_t const * const p_uuid_base, ble_uuid_t * p_uuid)
{
uint8_t uuid_base_le[16];
/* Reverse the bytes since ble_uuid128_t is LSB */
for(uint8_t i=0; i<16; i++)
{
uuid_base_le[i] = p_uuid_base[15-i];
}
ASSERT_STATUS( sd_ble_uuid_decode(16, uuid_base_le, p_uuid) );
return ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Adds a new characteristic to the custom service, assigning
properties, a UUID add-on value, etc.
@param[in] service_handle
@param[in] p_uuid The 16-bit value to add to the base UUID
for this characteristic (normally >1
since 1 is typically used by the primary
service).
@param[in] char_props The characteristic properties, as
defined by ble_gatt_char_props_t
@param[in] max_length The maximum length of this characeristic
@param[in] p_char_handle
@returns
@retval ERROR_NONE Everything executed normally
*/
/**************************************************************************/
error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t* p_uuid, uint8_t properties,
uint8_t *p_data, uint16_t min_length, uint16_t max_length,
ble_gatts_char_handles_t* p_char_handle)
{
/* Characteristic metadata */
ble_gatts_attr_md_t cccd_md;
ble_gatt_char_props_t char_props;
memcpy(&char_props, &properties, 1);
if ( char_props.notify || char_props.indicate )
{
/* Notification requires cccd */
memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t) );
cccd_md.vloc = BLE_GATTS_VLOC_STACK;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
}
ble_gatts_char_md_t char_md = { 0 };
char_md.char_props = char_props;
char_md.p_cccd_md = (char_props.notify || char_props.indicate ) ? &cccd_md : NULL;
/* Attribute declaration */
ble_gatts_attr_md_t attr_md = { 0 };
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.vlen = (min_length == max_length) ? 0 : 1;
if ( char_props.read || char_props.notify || char_props.indicate )
{
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
}
if ( char_props.write )
{
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
}
ble_gatts_attr_t attr_char_value = { 0 };
attr_char_value.p_uuid = p_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = min_length;
attr_char_value.max_len = max_length;
attr_char_value.p_value = p_data;
ASSERT_STATUS ( sd_ble_gatts_characteristic_add(service_handle,
&char_md,
&attr_char_value,
p_char_handle) );
return ERROR_NONE;
}

View File

@ -1,38 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 _CUSTOM_HELPER_H_
#define _CUSTOM_HELPER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "common/common.h"
#include "ble.h"
uint8_t custom_add_uuid_base(uint8_t const * const p_uuid_base);
error_t custom_decode_uuid(uint8_t const * const p_uuid_base, ble_uuid_t * p_uuid);
error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t* p_uuid, uint8_t properties,
uint8_t *p_data, uint16_t min_length, uint16_t max_length,
ble_gatts_char_handles_t* p_char_handle);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,103 +0,0 @@
/**************************************************************************/
/*!
@file ansi_esc_code.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This file is part of the tinyusb stack.
*/
/**************************************************************************/
/** \file
* \brief TBD
*
* \note TBD
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _ANSI_ESC_CODE_H_
#define _ANSI_ESC_CODE_H_
#ifdef __cplusplus
extern "C" {
#endif
#define CSI_CODE(seq) "\33[" seq
#define CSI_SGR(x) CSI_CODE(#x) "m"
//------------- Cursor movement -------------//
#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A")
#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B")
#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C")
#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D")
#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E")
#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F")
#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H")
#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J")
#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K")
/** text color */
#define ANSI_TEXT_BLACK CSI_SGR(30)
#define ANSI_TEXT_RED CSI_SGR(31)
#define ANSI_TEXT_GREEN CSI_SGR(32)
#define ANSI_TEXT_YELLOW CSI_SGR(33)
#define ANSI_TEXT_BLUE CSI_SGR(34)
#define ANSI_TEXT_MAGENTA CSI_SGR(35)
#define ANSI_TEXT_CYAN CSI_SGR(36)
#define ANSI_TEXT_WHITE CSI_SGR(37)
#define ANSI_TEXT_DEFAULT CSI_SGR(39)
/** background color */
#define ANSI_BG_BLACK CSI_SGR(40)
#define ANSI_BG_RED CSI_SGR(41)
#define ANSI_BG_GREEN CSI_SGR(42)
#define ANSI_BG_YELLOW CSI_SGR(43)
#define ANSI_BG_BLUE CSI_SGR(44)
#define ANSI_BG_MAGENTA CSI_SGR(45)
#define ANSI_BG_CYAN CSI_SGR(46)
#define ANSI_BG_WHITE CSI_SGR(47)
#define ANSI_BG_DEFAULT CSI_SGR(49)
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_ANSI_ESC_CODE_H_ */
/** @} */

View File

@ -1,200 +0,0 @@
/**************************************************************************/
/*!
@file assertion.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \file
* \brief TBD
*
* \note TBD
*/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _ASSERTION_H_
#define _ASSERTION_H_
#include "projectconfig.h"
#ifdef __cplusplus
extern "C"
{
#endif
static inline void debugger_breakpoint(void) ATTR_ALWAYS_INLINE;
static inline void debugger_breakpoint(void)
{
#ifndef _TEST_
__asm("BKPT #0\n");
#endif
}
//--------------------------------------------------------------------+
// Compile-time Assert
//--------------------------------------------------------------------+
#if defined __COUNTER__ && __COUNTER__ != __COUNTER__
#define _ASSERT_COUNTER __COUNTER__
#else
#define _ASSERT_COUNTER __LINE__
#endif
#define ASSERT_STATIC(const_expr, message) enum { XSTRING_CONCAT_(static_assert_, _ASSERT_COUNTER) = 1/(!!(const_expr)) }
//--------------------------------------------------------------------+
// Assert Helper
//--------------------------------------------------------------------+
//#ifndef _TEST_
// #define ASSERT_MESSAGE(format, ...)\
// _PRINTF("Assert at %s: %s: %d: " format "\n", __BASE_FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
//#else
// #define ASSERT_MESSAGE(format, ...)\
// _PRINTF("%d:note: Assert " format "\n", __LINE__, __VA_ARGS__)
//#endif
#if CFG_DEBUG == 3
#define ASSERT_MESSAGE(format, ...) debugger_breakpoint()
#elif CFG_DEBUG == 2
#define ASSERT_MESSAGE(format, ...) printf("Assert at %s: %s: %d: " format "\n", __BASE_FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
#else
#define ASSERT_MESSAGE(format, ...)
#endif
#define ASSERT_ERROR_HANDLER(x, para) \
return (x)
#define ASSERT_DEFINE_WITH_HANDLER(error_handler, handler_para, setup_statement, condition, error, format, ...) \
do{\
setup_statement;\
if (!(condition)) {\
ASSERT_MESSAGE(format, __VA_ARGS__);\
error_handler(error, handler_para);\
}\
}while(0)
#define ASSERT_DEFINE(...) ASSERT_DEFINE_WITH_HANDLER(ASSERT_ERROR_HANDLER, NULL, __VA_ARGS__)
//--------------------------------------------------------------------+
// error_t Status Assert TODO use ASSERT_DEFINE
//--------------------------------------------------------------------+
#define ASSERT_STATUS_MESSAGE(sts, message) \
ASSERT_DEFINE(error_t status = (error_t)(sts),\
ERROR_NONE == status, status, "%s: %s", ErrorStr[status], message)
#define ASSERT_STATUS(sts) \
ASSERT_DEFINE(error_t status = (error_t)(sts),\
ERROR_NONE == status, status, "error = %d", status)
#define ASSERT_STATUS_RET_VOID(sts) \
ASSERT_DEFINE(error_t status = (error_t)(sts),\
ERROR_NONE == status, (void) 0, "error = %d", status)
//--------------------------------------------------------------------+
// Logical Assert
//--------------------------------------------------------------------+
#define ASSERT(...) ASSERT_TRUE(__VA_ARGS__)
#define ASSERT_TRUE(condition , error) ASSERT_DEFINE( , (condition), error, "%s", "evaluated to false")
#define ASSERT_FALSE(condition , error) ASSERT_DEFINE( ,!(condition), error, "%s", "evaluated to true")
//--------------------------------------------------------------------+
// Pointer Assert
//--------------------------------------------------------------------+
#define ASSERT_PTR(...) ASSERT_PTR_NOT_NULL(__VA_ARGS__)
#define ASSERT_PTR_NOT_NULL(pointer, error) ASSERT_DEFINE( , NULL != (pointer), error, "%s", "pointer is NULL")
#define ASSERT_PTR_NULL(pointer, error) ASSERT_DEFINE( , NULL == (pointer), error, "%s", "pointer is not NULL")
//--------------------------------------------------------------------+
// Integral Assert
//--------------------------------------------------------------------+
#define ASSERT_XXX_EQUAL(type_format, expected, actual, error) \
ASSERT_DEFINE(\
uint32_t exp = (expected); uint32_t act = (actual),\
exp==act,\
error,\
"expected " type_format ", actual " type_format, exp, act)
#define ASSERT_XXX_WITHIN(type_format, lower, upper, actual, error) \
ASSERT_DEFINE(\
uint32_t low = (lower); uint32_t up = (upper); uint32_t act = (actual),\
(low <= act) && (act <= up),\
error,\
"expected within " type_format " - " type_format ", actual " type_format, low, up, act)
//--------------------------------------------------------------------+
// Integer Assert
//--------------------------------------------------------------------+
#define ASSERT_INT(...) ASSERT_INT_EQUAL(__VA_ARGS__)
#define ASSERT_INT_EQUAL(...) ASSERT_XXX_EQUAL("%d", __VA_ARGS__)
#define ASSERT_INT_WITHIN(...) ASSERT_XXX_WITHIN("%d", __VA_ARGS__)
//--------------------------------------------------------------------+
// Hex Assert
//--------------------------------------------------------------------+
#define ASSERT_HEX(...) ASSERT_HEX_EQUAL(__VA_ARGS__)
#define ASSERT_HEX_EQUAL(...) ASSERT_XXX_EQUAL("0x%x", __VA_ARGS__)
#define ASSERT_HEX_WITHIN(...) ASSERT_XXX_WITHIN("0x%x", __VA_ARGS__)
//--------------------------------------------------------------------+
// Bin Assert
//--------------------------------------------------------------------+
#define BIN8_PRINTF_PATTERN "%d%d%d%d%d%d%d%d"
#define BIN8_PRINTF_CONVERT(byte) \
((byte) & 0x80 ? 1 : 0), \
((byte) & 0x40 ? 1 : 0), \
((byte) & 0x20 ? 1 : 0), \
((byte) & 0x10 ? 1 : 0), \
((byte) & 0x08 ? 1 : 0), \
((byte) & 0x04 ? 1 : 0), \
((byte) & 0x02 ? 1 : 0), \
((byte) & 0x01 ? 1 : 0)
#define ASSERT_BIN8(...) ASSERT_BIN8_EQUAL(__VA_ARGS__)
#define ASSERT_BIN8_EQUAL(expected, actual, error)\
ASSERT_DEFINE(\
uint8_t exp = (expected); uint8_t act = (actual),\
exp==act,\
error,\
"expected " BIN8_PRINTF_PATTERN ", actual " BIN8_PRINTF_PATTERN, BIN8_PRINTF_CONVERT(exp), BIN8_PRINTF_CONVERT(act) )
#ifdef __cplusplus
}
#endif
#endif /* _ASSERTION_H_ */
/** @} */

View File

@ -1,96 +0,0 @@
/**************************************************************************/
/*!
@file binary.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \ingroup TBD
* \defgroup TBD
* \brief TBD
*
* @{
*/
#ifndef _BINARY_H_
#define _BINARY_H_
#ifdef __cplusplus
extern "C" {
#endif
/// n-th Bit
#define BIT(n) (1 << (n))
/// set n-th bit of x to 1
#define BIT_SET(x, n) ( (x) | BIT(n) )
/// clear n-th bit of x
#define BIT_CLR(x, n) ( (x) & (~BIT(n)) )
/// test n-th bit of x
#define BIT_TEST(x, n) ( (x) & BIT(n) )
#if defined(__GNUC__) && !defined(__CC_ARM) // keil does not support binary format
#define BIN8(x) ((uint8_t) (0b##x))
#define BIN16(b1, b2) ((uint16_t) (0b##b1##b2))
#define BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4))
#else
// internal macro of B8, B16, B32
#define _B8__(x) (((x&0x0000000FUL)?1:0) \
+((x&0x000000F0UL)?2:0) \
+((x&0x00000F00UL)?4:0) \
+((x&0x0000F000UL)?8:0) \
+((x&0x000F0000UL)?16:0) \
+((x&0x00F00000UL)?32:0) \
+((x&0x0F000000UL)?64:0) \
+((x&0xF0000000UL)?128:0))
#define BIN8(d) ((uint8_t) _B8__(0x##d##UL))
#define BIN16(dmsb,dlsb) (((uint16_t)BIN8(dmsb)<<8) + BIN8(dlsb))
#define BIN32(dmsb,db2,db3,dlsb) \
(((uint32_t)BIN8(dmsb)<<24) \
+ ((uint32_t)BIN8(db2)<<16) \
+ ((uint32_t)BIN8(db3)<<8) \
+ BIN8(dlsb))
#endif
#ifdef __cplusplus
}
#endif
#endif /* _BINARY_H_ */
/** @} */

View File

@ -1,151 +0,0 @@
/**************************************************************************/
/*!
@file ble_error.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \file
* \brief Error Header
*
* \note TBD
*/
/** \ingroup Group_Common
* \defgroup Group_Error Error Codes
* @{
*/
#ifndef _BLE_ERROR_H_
#define _BLE_ERROR_H_
#include "projectconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
/*=======================================================================
NORDIC GLOBAL ERRORS 0x0000 .. 0x00FF
-----------------------------------------------------------------------
Errors mapped from nrf_error.h
-----------------------------------------------------------------------*/
ERROR_NONE = 0x0000 , ///< Successful command
ERROR_SVC_HANDLER_MISSING = 0x0001 , ///< SVC handler is missing
ERROR_SOFTDEVICE_NOT_ENABLED = 0x0002 , ///< SoftDevice has not been enabled
ERROR_INTERNAL = 0x0003 , ///< Internal Error
ERROR_NO_MEM = 0x0004 , ///< No Memory for operation
ERROR_NOT_FOUND = 0x0005 , ///< Not found
ERROR_NOT_SUPPORTED = 0x0006 , ///< Not supported
ERROR_INVALID_PARAM = 0x0007 , ///< Invalid Parameter
ERROR_INVALID_STATE = 0x0008 , ///< Invalid state, operation disallowed in this state
ERROR_INVALID_LENGTH = 0x0009 , ///< Invalid Length
ERROR_INVALID_FLAGS = 0x000A , ///< Invalid Flags
ERROR_INVALID_DATA = 0x000B , ///< Invalid Data
ERROR_DATA_SIZE = 0x000C , ///< Data size exceeds limit
ERROR_TIMEOUT = 0x000D , ///< Operation timed out
ERROR_NULL = 0x000E , ///< Null Pointer
ERROR_FORBIDDEN = 0x000F , ///< Forbidden Operation
ERROR_INVALID_ADDR = 0x0010 , ///< Bad Memory Address
ERROR_BUSY = 0x0011 , ///< Busy
/*=======================================================================*/
ERROR_INVALIDPARAMETER = 0x0100 , /**< An invalid parameter value was provided */
ERROR_I2C_XFER_FAILED = 0x0101 , /**< an failed attempt to make I2C transfer */
/*=======================================================================
SIMPLE BINARY PROTOCOL ERRORS 0x0120 .. 0x013F
-----------------------------------------------------------------------
Errors relating to the simple binary protocol (/src//protocol)
-----------------------------------------------------------------------*/
ERROR_PROT_INVALIDMSGTYPE = 0x121, /**< Unexpected msg type encountered */
ERROR_PROT_INVALIDCOMMANDID = 0x122, /**< Unknown or out of range command ID */
ERROR_PROT_INVALIDPAYLOAD = 0x123, /**< Message payload has a problem (invalid len, etc.) */
/*=======================================================================*/
//------------- based on Nordic SDM nrf_error_sdm.h -------------//
ERROR_SDM_LFCLK_SOURCE_UNKNOWN = 0x1000 , ///< Unknown lfclk source
ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION = 0x1001 , ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts)
ERROR_SDM_INCORRECT_CLENR0 = 0x1002 , ///< Incorrect CLENR0 (can be caused by erronous SoftDevice flashing)
//------------- based on Nordic SOC nrf_error_soc.h -------------//
/* Mutex Errors */
ERROR_SOC_MUTEX_ALREADY_TAKEN = 0x2000 , ///< Mutex already taken
/* NVIC errors */
ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE = 0x2001 , ///< NVIC interrupt not available
ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED = 0x2002 , ///< NVIC interrupt priority not allowed
ERROR_SOC_NVIC_SHOULD_NOT_RETURN = 0x2003 , ///< NVIC should not return
/* Power errors */
ERROR_SOC_POWER_MODE_UNKNOWN = 0x2004 , ///< Power mode unknown
ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN = 0x2005 , ///< Power POF threshold unknown
ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN = 0x2006 , ///< Power off should not return
/* Rand errors */
ERROR_SOC_RAND_NOT_ENOUGH_VALUES = 0x2007 , ///< RAND not enough values
/* PPI errors */
ERROR_SOC_PPI_INVALID_CHANNEL = 0x2008 , ///< Invalid PPI Channel
ERROR_SOC_PPI_INVALID_GROUP = 0x2009 , ///< Invalid PPI Group
//------------- based on Nordic STK (ble) ble_err.h -------------//
ERROR_BLE_INVALID_CONN_HANDLE = 0x3001 , /**< Invalid connection handle. */
ERROR_BLE_INVALID_ATTR_HANDLE = 0x3002 , /**< Invalid attribute handle. */
ERROR_BLE_NO_TX_BUFFERS = 0x3003 , /**< Buffer capacity exceeded. */
// L2CAP
ERROR_BLE_L2CAP_CID_IN_USE = 0x3100 , /**< CID already in use. */
// GAP
ERROR_BLE_GAP_UUID_LIST_MISMATCH = 0x3200 , /**< UUID list does not contain an integral number of UUIDs. */
ERROR_BLE_GAP_DISCOVERABLE_WITH_WHITELIST = 0x3201 , /**< Use of Whitelist not permitted with discoverable advertising. */
ERROR_BLE_GAP_INVALID_BLE_ADDR = 0x3202 , /**< The upper two bits of the address do not correspond to the specified address type. */
// GATTC
ERROR_BLE_GATTC_PROC_NOT_PERMITTED = 0x3300 ,
// GATTS
ERROR_BLEGATTS_INVALID_ATTR_TYPE = 0x3400 , /**< Invalid attribute type. */
ERROR_BLEGATTS_SYS_ATTR_MISSING = 0x3401 , /**< System Attributes missing. */
}error_t;
#ifdef __cplusplus
}
#endif
#endif /* _BLE_ERROR_H_ */
/** @} */

View File

@ -1,236 +0,0 @@
/**************************************************************************/
/*!
@file common.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \defgroup Group_Common Common Files
* @{
*
* \defgroup Group_CommonH common.h
*
* @{
*/
#ifndef _COMMON_H_
#define _COMMON_H_
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------+
// INCLUDES
//--------------------------------------------------------------------+
//------------- Standard Header -------------//
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
//------------- General Header -------------//
#include "projectconfig.h"
#include "compiler.h"
#include "assertion.h"
#include "binary.h"
#include "ble_error.h"
//------------- MCU header -------------//
//#include "nrf.h"
//--------------------------------------------------------------------+
// TYPEDEFS
//--------------------------------------------------------------------+
typedef unsigned char byte_t;
typedef float float32_t;
typedef double float64_t;
//--------------------------------------------------------------------+
// MACROS
//--------------------------------------------------------------------+
#define STRING_(x) #x // stringify without expand
#define XSTRING_(x) STRING_(x) // expand then stringify
#define STRING_CONCAT_(a, b) a##b // concat without expand
#define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) // expand then concat
#define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff))
#define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff))
#define U16_TO_U8S_BE(u16) U16_HIGH_U8(u16), U16_LOW_U8(u16)
#define U16_TO_U8S_LE(u16) U16_LOW_U8(u16), U16_HIGH_U8(u16)
#define U32_B1_U8(u32) ((uint8_t) (((u32) >> 24) & 0x000000ff)) // MSB
#define U32_B2_U8(u32) ((uint8_t) (((u32) >> 16) & 0x000000ff))
#define U32_B3_U8(u32) ((uint8_t) (((u32) >> 8) & 0x000000ff))
#define U32_B4_U8(u32) ((uint8_t) ((u32) & 0x000000ff)) // LSB
#define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32)
#define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32)
//--------------------------------------------------------------------+
// INLINE FUNCTION
//--------------------------------------------------------------------+
#define memclr_(buffer, size) memset(buffer, 0, size)
//------------- Conversion -------------//
/// form an uint32_t from 4 x uint8_t
static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4)
{
return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
}
static inline uint8_t u16_high_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE;
static inline uint8_t u16_high_u8(uint16_t u16)
{
return (uint8_t) ((u16 >> 8) & 0x00ff);
}
static inline uint8_t u16_low_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE;
static inline uint8_t u16_low_u8(uint16_t u16)
{
return (uint8_t) (u16 & 0x00ff);
}
//------------- Min -------------//
static inline uint8_t min8_of(uint8_t x, uint8_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint8_t min8_of(uint8_t x, uint8_t y)
{
return (x < y) ? x : y;
}
static inline uint16_t min16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint16_t min16_of(uint16_t x, uint16_t y)
{
return (x < y) ? x : y;
}
static inline uint32_t min32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t min32_of(uint32_t x, uint32_t y)
{
return (x < y) ? x : y;
}
//------------- Max -------------//
static inline uint32_t max32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t max32_of(uint32_t x, uint32_t y)
{
return (x > y) ? x : y;
}
//------------- Align -------------//
static inline uint32_t align32 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t align32 (uint32_t value)
{
return (value & 0xFFFFFFE0UL);
}
static inline uint32_t align16 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t align16 (uint32_t value)
{
return (value & 0xFFFFFFF0UL);
}
static inline uint32_t align_n (uint32_t alignment, uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t align_n (uint32_t alignment, uint32_t value)
{
return value & (~(alignment-1));
}
static inline uint32_t align4k (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t align4k (uint32_t value)
{
return (value & 0xFFFFF000UL);
}
static inline uint32_t offset4k(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint32_t offset4k(uint32_t value)
{
return (value & 0xFFFUL);
}
//------------- Mathematics -------------//
/// inclusive range checking
static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper)
{
return (lower <= value) && (value <= upper);
}
/// exclusive range checking
static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper)
{
return (lower < value) && (value < upper);
}
static inline uint8_t log2_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint8_t log2_of(uint32_t value)
{
uint8_t result = 0; // log2 of a value is its MSB's position
while (value >>= 1)
{
result++;
}
return result;
}
// return the number of set bits in value
static inline uint8_t cardinality_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint8_t cardinality_of(uint32_t value)
{
// Brian Kernighan's method goes through as many iterations as there are set bits. So if we have a 32-bit word with only
// the high bit set, then it will only go once through the loop
// Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie)
// mentions this in exercise 2-9. On April 19, 2006 Don Knuth pointed out to me that this method
// "was first published by Peter Wegner in CACM 3 (1960), 322. (Also discovered independently by Derrick Lehmer and
// published in 1964 in a book edited by Beckenbach.)"
uint8_t count;
for (count = 0; value; count++)
{
value &= value - 1; // clear the least significant bit set
}
return count;
}
#ifdef __cplusplus
}
#endif
#endif /* _COMMON_H_ */
/** @} */
/** @} */

View File

@ -1,152 +0,0 @@
/**************************************************************************/
/*!
@file compiler.h
@author hathach (tinyusb.org)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2013, K. Townsend (microBuilder.eu)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
/** \file
* \brief GCC Header
*/
/** \ingroup Group_Compiler
* \defgroup Group_GCC GNU GCC
* @{
*/
#ifndef _COMPILER_GCC_H_
#define _COMPILER_GCC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "projectconfig.h"
//#ifndef __GNUC__
// #define ATTR_ALWAYS_INLINE
// #define ATTR_CONST
//#else
#ifdef _TEST_
#define ATTR_ALWAYS_INLINE
#define STATIC_
#define INLINE_
#else
#define STATIC_ static
#define INLINE_ inline
#if CFG_DEBUG == 3
#define ATTR_ALWAYS_INLINE // no inline for debug = 3
#endif
#endif
#define ALIGN_OF(x) __alignof__(x)
/// Normally, the compiler places the objects it generates in sections like data or bss & function in text. Sometimes, however, you need additional sections, or you need certain particular variables to appear in special sections, for example to map to special hardware. The section attribute specifies that a variable (or function) lives in a particular section
#define ATTR_SECTION(section) __attribute__ ((#section))
/// If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, an error that includes message is diagnosed. This is useful for compile-time checking
#define ATTR_ERROR(Message) __attribute__ ((error(Message)))
/// If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, a warning that includes message is diagnosed. This is useful for compile-time checking
#define ATTR_WARNING(Message) __attribute__ ((warning(Message)))
/**
* \defgroup Group_VariableAttr Variable Attributes
* @{
*/
/// This attribute specifies a minimum alignment for the variable or structure field, measured in bytes
#define ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
/// The packed attribute specifies that a variable or structure field should have the smallest possible alignment—one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute
#define ATTR_PACKED __attribute__ ((packed))
#define ATTR_PREPACKED
#define ATTR_PACKED_STRUCT(x) x __attribute__ ((packed))
/** @} */
/**
* \defgroup Group_FuncAttr Function Attributes
* @{
*/
#ifndef ATTR_ALWAYS_INLINE
/// Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function even if no optimization level is specified
#define ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#endif
/// The nonnull attribute specifies that some function parameters should be non-null pointers. f the compiler determines that a null pointer is passed in an argument slot marked as non-null, and the -Wnonnull option is enabled, a warning is issued. All pointer arguments are marked as non-null
#define ATTR_NON_NULL __attribute__ ((nonull))
/// Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the attribute pure
#define ATTR_PURE __attribute__ ((pure))
/// Many functions do not examine any values except their arguments, and have no effects except the return value. Basically this is just slightly more strict class than the pure attribute below, since function is not allowed to read global memory.
/// Note that a function that has pointer arguments and examines the data pointed to must not be declared const. Likewise, a function that calls a non-const function usually must not be const. It does not make sense for a const function to return void
#define ATTR_CONST __attribute__ ((const))
/// The deprecated attribute results in a warning if the function is used anywhere in the source file. This is useful when identifying functions that are expected to be removed in a future version of a program. The warning also includes the location of the declaration of the deprecated function, to enable users to easily find further information about why the function is deprecated, or what they should do instead. Note that the warnings only occurs for uses
#define ATTR_DEPRECATED __attribute__ ((deprecated))
/// Same as the deprecated attribute with optional message in the warning
#define ATTR_DEPRECATED_MESS(mess) __attribute__ ((deprecated(mess)))
/// The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions that can be overridden in user code
#define ATTR_WEAK __attribute__ ((weak))
/// The alias attribute causes the declaration to be emitted as an alias for another symbol, which must be specified
#define ATTR_ALIAS(func) __attribute__ ((alias(#func)))
/// The weakref attribute marks a declaration as a weak reference. It is equivalent with weak + alias attribute, but require function is static
#define ATTR_WEAKREF(func) __attribute__ ((weakref(#func)))
/// The warn_unused_result attribute causes a warning to be emitted if a caller of the function with this attribute does not use its return value. This is useful for functions where not checking the result is either a security problem or always a bug
#define ATTR_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
/// This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.
#define ATTR_USED __attribute__ ((used))
/// This attribute, attached to a function, means that the function is meant to be possibly unused. GCC does not produce a warning for this function.
#define ATTR_UNUSED __attribute__ ((unused))
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _COMPILER_GCC_H_ */
/// @}

View File

@ -1,89 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 "mbed.h"
#include "nRF51822n.h"
#include "btle/btle.h"
/**************************************************************************/
/*!
@brief Constructor
*/
/**************************************************************************/
nRF51822n::nRF51822n(void)
{
}
/**************************************************************************/
/*!
@brief Destructor
*/
/**************************************************************************/
nRF51822n::~nRF51822n(void)
{
}
/**************************************************************************/
/*!
@brief Initialises anything required to start using BLE
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51822n::init(void)
{
/* ToDo: Clear memory contents, reset the SD, etc. */
btle_init();
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Resets the BLE HW, removing any existing services and
characteristics
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51822n::reset(void)
{
wait(0.5);
/* Wait for the radio to come back up */
wait(1);
return BLE_ERROR_NONE;
}

View File

@ -1,49 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __NRF51822_H__
#define __NRF51822_H__
#define NRF51
#define DEBUG_NRF_USER
#define BLE_STACK_SUPPORT_REQD
#define BOARD_PCA10001
#include "mbed.h"
#include "blecommon.h"
#include "hw/BLEDevice.h"
#include "nRF51Gap.h"
#include "nRF51GattServer.h"
/**************************************************************************/
/*!
\brief
*/
/**************************************************************************/
class nRF51822n : public BLEDevice
{
public:
nRF51822n(void);
virtual ~nRF51822n(void);
virtual Gap& getGap() { return nRF51Gap::getInstance(); };
virtual GattServer& getGattServer() { return nRF51GattServer::getInstance(); };
virtual ble_error_t init(void);
virtual ble_error_t reset(void);
};
#endif

View File

@ -1,284 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 "nRF51Gap.h"
#include "mbed.h"
#include "common/common.h"
#include "ble_advdata.h"
#include "ble_hci.h"
/**************************************************************************/
/*!
@brief Sets the advertising parameters and payload for the device
@param[in] params
Basic advertising details, including the advertising
delay, timeout and how the device should be advertised
@params[in] advData
The primary advertising data payload
@params[in] scanResponse
The optional Scan Response payload if the advertising
type is set to \ref GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED
in \ref GapAdveritinngParams
@returns \ref ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@retval BLE_ERROR_BUFFER_OVERFLOW
The proposed action would cause a buffer overflow. All
advertising payloads must be <= 31 bytes, for example.
@retval BLE_ERROR_NOT_IMPLEMENTED
A feature was requested that is not yet supported in the
nRF51 firmware or hardware.
@retval BLE_ERROR_PARAM_OUT_OF_RANGE
One of the proposed values is outside the valid range.
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51Gap::setAdvertisingData(GapAdvertisingData & advData, GapAdvertisingData & scanResponse)
{
/* Make sure we don't exceed the advertising payload length */
if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD)
{
return BLE_ERROR_BUFFER_OVERFLOW;
}
/* Make sure we have a payload! */
if (advData.getPayloadLen() == 0)
{
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
/* Check the scan response payload limits */
//if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED))
//{
// /* Check if we're within the upper limit */
// if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD)
// {
// return BLE_ERROR_BUFFER_OVERFLOW;
// }
// /* Make sure we have a payload! */
// if (advData.getPayloadLen() == 0)
// {
// return BLE_ERROR_PARAM_OUT_OF_RANGE;
// }
//}
/* Send advertising data! */
ASSERT( ERROR_NONE == sd_ble_gap_adv_data_set(advData.getPayload(), advData.getPayloadLen(),
scanResponse.getPayload(), scanResponse.getPayloadLen()), BLE_ERROR_PARAM_OUT_OF_RANGE);
/* Make sure the GAP Service appearance value is aligned with the appearance from GapAdvertisingData */
ASSERT( ERROR_NONE == sd_ble_gap_appearance_set(advData.getAppearance()), BLE_ERROR_PARAM_OUT_OF_RANGE);
/* ToDo: Perform some checks on the payload, for example the Scan Response can't */
/* contains a flags AD type, etc. */
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Starts the BLE HW, initialising any services that were
added before this function was called.
@note All services must be added before calling this function!
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51Gap::startAdvertising(GapAdvertisingParams & params)
{
/* Make sure we support the advertising type */
if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED)
{
/* ToDo: This requires a propery security implementation, etc. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
/* Check interval range */
if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)
{
/* Min delay is slightly longer for unconnectable devices */
if ((params.getInterval() < GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) ||
(params.getInterval() > GAP_ADV_PARAMS_INTERVAL_MAX))
{
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
else
{
if ((params.getInterval() < GAP_ADV_PARAMS_INTERVAL_MIN) ||
(params.getInterval() > GAP_ADV_PARAMS_INTERVAL_MAX))
{
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
/* Check timeout is zero for Connectable Directed */
if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) &&
(params.getTimeout() != 0))
{
/* Timeout must be 0 with this type, although we'll never get here */
/* since this isn't implemented yet anyway */
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
/* Check timeout for other advertising types */
if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) &&
(params.getTimeout() > GAP_ADV_PARAMS_TIMEOUT_MAX))
{
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
/* Start Advertising */
ble_gap_adv_params_t adv_para = { 0 };
adv_para.type = params.getAdvertisingType() ;
adv_para.p_peer_addr = NULL ; // Undirected advertisement
adv_para.fp = BLE_GAP_ADV_FP_ANY ;
adv_para.p_whitelist = NULL ;
adv_para.interval = params.getInterval() ; // advertising interval (in units of 0.625 ms)
adv_para.timeout = params.getTimeout() ;
ASSERT( ERROR_NONE == sd_ble_gap_adv_start(&adv_para), BLE_ERROR_PARAM_OUT_OF_RANGE);
state.advertising = 1;
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Stops the BLE HW and disconnects from any devices
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51Gap::stopAdvertising(void)
{
/* Stop Advertising */
ASSERT( ERROR_NONE == sd_ble_gap_adv_stop(), BLE_ERROR_PARAM_OUT_OF_RANGE);
state.advertising = 0;
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Disconnects if we are connected to a central device
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51Gap::disconnect(void)
{
state.advertising = 0;
state.connected = 0;
/* Disconnect if we are connected to a central device */
ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(m_connectionHandle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION),
BLE_ERROR_PARAM_OUT_OF_RANGE);
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Sets the 16-bit connection handle
*/
/**************************************************************************/
void nRF51Gap::setConnectionHandle(uint16_t con_handle)
{
m_connectionHandle = con_handle;
}
/**************************************************************************/
/*!
@brief Gets the 16-bit connection handle
*/
/**************************************************************************/
uint16_t nRF51Gap::getConnectionHandle(void)
{
return m_connectionHandle;
}
/**************************************************************************/
/*!
@brief Sets the BLE device address
@returns ble_error_t
@section EXAMPLE
@code
uint8_t device_address[6] = { 0xca, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0 };
nrf.getGap().setAddress(Gap::ADDR_TYPE_RANDOM_STATIC, device_address);
@endcode
*/
/**************************************************************************/
ble_error_t nRF51Gap::setAddress(addr_type_t type, uint8_t address[6])
{
if ( type > ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) return BLE_ERROR_PARAM_OUT_OF_RANGE;
ble_gap_addr_t dev_addr;
dev_addr.addr_type = type;
memcpy(dev_addr.addr, address, 6);
ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(&dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE);
return BLE_ERROR_NONE;
}

View File

@ -1,59 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __NRF51822_GAP_H__
#define __NRF51822_GAP_H__
#include "mbed.h"
#include "blecommon.h"
#include "ble.h"
#include "GapAdvertisingParams.h"
#include "GapAdvertisingData.h"
#include "hw/Gap.h"
/**************************************************************************/
/*!
\brief
*/
/**************************************************************************/
class nRF51Gap : public Gap
{
public:
static nRF51Gap& getInstance()
{
static nRF51Gap m_instance;
return m_instance;
}
/* Functions that must be implemented from Gap */
virtual ble_error_t setAddress(addr_type_t type, uint8_t address[6]);
virtual ble_error_t setAdvertisingData(GapAdvertisingData &, GapAdvertisingData &);
virtual ble_error_t startAdvertising(GapAdvertisingParams &);
virtual ble_error_t stopAdvertising(void);
virtual ble_error_t disconnect(void);
void setConnectionHandle(uint16_t con_handle);
uint16_t getConnectionHandle(void);
private:
uint16_t m_connectionHandle;
nRF51Gap() { m_connectionHandle = BLE_CONN_HANDLE_INVALID; };
nRF51Gap(nRF51Gap const&);
void operator=(nRF51Gap const&);
};
#endif

View File

@ -1,241 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 "nRF51GattServer.h"
#include "mbed.h"
#include "common/common.h"
#include "btle/custom/custom_helper.h"
#include "nRF51Gap.h"
/**************************************************************************/
/*!
@brief Adds a new service to the GATT table on the peripheral
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51GattServer::addService(GattService & service)
{
/* ToDo: Make sure we don't overflow the array, etc. */
/* ToDo: Make sure this service UUID doesn't already exist (?) */
/* ToDo: Basic validation */
/* Add the service to the nRF51 */
ble_uuid_t uuid;
if (service.primaryServiceID.type == UUID::UUID_TYPE_SHORT)
{
/* 16-bit BLE UUID */
uuid.type = BLE_UUID_TYPE_BLE;
}
else
{
/* 128-bit Custom UUID */
uuid.type = custom_add_uuid_base( service.primaryServiceID.base );
}
uuid.uuid = service.primaryServiceID.value;
ASSERT( ERROR_NONE == sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &uuid, &service.handle), BLE_ERROR_PARAM_OUT_OF_RANGE );
/* Add characteristics to the service */
for (uint8_t i = 0; i < service.characteristicCount; i++)
{
GattCharacteristic * p_char = service.characteristics[i];
uuid.uuid = p_char->uuid;
ASSERT ( ERROR_NONE == custom_add_in_characteristic(service.handle, &uuid, p_char->properties,
NULL, p_char->lenMin, p_char->lenMax, &nrfCharacteristicHandles[characteristicCount]), BLE_ERROR_PARAM_OUT_OF_RANGE );
/* Update the characteristic handle */
p_char->handle = characteristicCount;
p_characteristics[characteristicCount++] = p_char;
}
serviceCount++;
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Reads the value of a characteristic, based on the service
and characteristic index fields
@param[in] charHandle
The handle of the GattCharacteristic to read from
@param[in] buffer
Buffer to hold the the characteristic's value
(raw byte array in LSB format)
@param[in] len
The number of bytes read into the buffer
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51GattServer::readValue(uint16_t charHandle, uint8_t buffer[], uint16_t len)
{
ASSERT( ERROR_NONE == sd_ble_gatts_value_get(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE);
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Updates the value of a characteristic, based on the service
and characteristic index fields
@param[in] charHandle
The handle of the GattCharacteristic to write to
@param[in] buffer
Data to use when updating the characteristic's value
(raw byte array in LSB format)
@param[in] len
The number of bytes in buffer
@returns ble_error_t
@retval BLE_ERROR_NONE
Everything executed properly
@section EXAMPLE
@code
@endcode
*/
/**************************************************************************/
ble_error_t nRF51GattServer::updateValue(uint16_t charHandle, uint8_t buffer[], uint16_t len, bool localOnly)
{
uint16_t gapConnectionHandle = nRF51Gap::getInstance().getConnectionHandle();
if (localOnly)
{
/* Only update locally regardless of notify/indicate */
ASSERT_INT( ERROR_NONE, sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE );
}
if ((p_characteristics[charHandle]->properties & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
(gapConnectionHandle != BLE_CONN_HANDLE_INVALID) )
{
/* HVX update for the characteristic value */
ble_gatts_hvx_params_t hvx_params;
hvx_params.handle = nrfCharacteristicHandles[charHandle].value_handle;
hvx_params.type = (p_characteristics[charHandle]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION;
hvx_params.offset = 0;
hvx_params.p_data = buffer;
hvx_params.p_len = &len;
error_t error = (error_t) sd_ble_gatts_hvx(gapConnectionHandle, &hvx_params);
/* ERROR_INVALID_STATE, ERROR_BUSY, ERROR_GATTS_SYS_ATTR_MISSING and ERROR_NO_TX_BUFFERS the ATT table has been updated. */
if ( (error != ERROR_NONE ) && (error != ERROR_INVALID_STATE) &&
(error != ERROR_BLE_NO_TX_BUFFERS ) && (error != ERROR_BUSY ) &&
(error != ERROR_BLEGATTS_SYS_ATTR_MISSING ) )
{
ASSERT_INT( ERROR_NONE, sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE );
}
} else
{
ASSERT_INT( ERROR_NONE, sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE );
}
return BLE_ERROR_NONE;
}
/**************************************************************************/
/*!
@brief Callback handler for events getting pushed up from the SD
*/
/**************************************************************************/
void nRF51GattServer::hwCallback(ble_evt_t * p_ble_evt)
{
uint16_t handle_value;
GattServerEvents::gattEvent_t event;
switch (p_ble_evt->header.evt_id)
{
case BLE_GATTS_EVT_WRITE:
/* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */
/* 1.) Handle CCCD changes */
handle_value = p_ble_evt->evt.gatts_evt.params.write.handle;
for(uint8_t i=0; i<characteristicCount; i++)
{
if ( (p_characteristics[i]->properties & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
(nrfCharacteristicHandles[i].cccd_handle == handle_value) )
{
uint16_t cccd_value = (p_ble_evt->evt.gatts_evt.params.write.data[1] << 8) | p_ble_evt->evt.gatts_evt.params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
if ( ((p_characteristics[i]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION )) ||
((p_characteristics[i]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY ) && (cccd_value & BLE_GATT_HVX_NOTIFICATION)))
{
event = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
} else
{
event = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
}
handleEvent(event, i);
return;
}
}
/* 2.) Changes to the characteristic value will be handled with other events below */
event = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
break;
case BLE_GATTS_EVT_HVC:
/* Indication confirmation received */
event = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
handle_value = p_ble_evt->evt.gatts_evt.params.hvc.handle;
break;
default:
return;
}
/* Find index (charHandle) in the pool */
for(uint8_t i=0; i<characteristicCount; i++)
{
if (nrfCharacteristicHandles[i].value_handle == handle_value)
{
handleEvent(event, i);
break;
}
}
}

View File

@ -1,62 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* 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 __NRF51822_GATT_SERVER_H__
#define __NRF51822_GATT_SERVER_H__
#include "mbed.h"
#include "blecommon.h"
#include "ble.h" /* nordic ble */
#include "GattService.h"
#include "hw/GattServer.h"
#define BLE_TOTAL_CHARACTERISTICS 10
/**************************************************************************/
/*!
\brief
*/
/**************************************************************************/
class nRF51GattServer : public GattServer
{
public:
static nRF51GattServer& getInstance()
{
static nRF51GattServer m_instance;
return m_instance;
}
/* Functions that must be implemented from GattServer */
virtual ble_error_t addService(GattService &);
virtual ble_error_t readValue(uint16_t, uint8_t[], uint16_t);
virtual ble_error_t updateValue(uint16_t, uint8_t[], uint16_t, bool localOnly = false);
/* nRF51 Functions */
void eventCallback(void);
void hwCallback(ble_evt_t * p_ble_evt);
private:
GattCharacteristic* p_characteristics[BLE_TOTAL_CHARACTERISTICS];
ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS];
nRF51GattServer() { serviceCount = 0; characteristicCount = 0; };
nRF51GattServer(nRF51GattServer const&);
void operator=(nRF51GattServer const&);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +0,0 @@
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include "crc16.h"
#include <stdio.h>
uint16_t crc16_compute(const uint8_t * p_data, uint32_t size, const uint16_t * p_crc)
{
uint32_t i;
uint16_t crc = (p_crc == NULL) ? 0xffff : *p_crc;
for (i = 0; i < size; i++)
{
crc = (unsigned char)(crc >> 8) | (crc << 8);
crc ^= p_data[i];
crc ^= (unsigned char)(crc & 0xff) >> 4;
crc ^= (crc << 8) << 4;
crc ^= ((crc & 0xff) << 4) << 1;
}
return crc;
}

View File

@ -1,759 +0,0 @@
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf_error.h"
#include "nrf_assert.h"
//#include "nrf.h"
#include "nrf_soc.h"
#include "app_util.h"
#include "pstorage.h"
#define INVALID_OPCODE 0x00 /**< Invalid op code identifier. */
#define SOC_MAX_WRITE_SIZE 1024 /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API. */
/**
* @defgroup api_param_check API Parameters check macros.
*
* @details Macros that verify parameters passed to the module in the APIs. These macros
* could be mapped to nothing in final versions of code to save execution and size.
*
* @{
*/
/**
* @brief Check if the input pointer is NULL, if it is returns NRF_ERROR_NULL.
*/
#define NULL_PARAM_CHECK(PARAM) \
if ((PARAM) == NULL) \
{ \
return NRF_ERROR_NULL; \
}
/**
* @brief Verifies the module identifier supplied by the application is within permissible
* range.
*/
#define MODULE_ID_RANGE_CHECK(ID) \
if ((((ID)->module_id) >= PSTORAGE_MAX_APPLICATIONS) || \
(m_app_table[(ID)->module_id].cb == NULL)) \
{ \
return NRF_ERROR_INVALID_PARAM; \
}
/**
* @brief Verifies the block identifier supplied by the application is within the permissible
* range.
*/
#define BLOCK_ID_RANGE_CHECK(ID) \
if (((ID)->block_id) >= (m_app_table[(ID)->module_id].base_id + \
(m_app_table[(ID)->module_id].block_count * MODULE_BLOCK_SIZE(ID)))) \
{ \
return NRF_ERROR_INVALID_PARAM; \
}
/**
* @brief Verifies the block size requested by the application can be supported by the module.
*/
#define BLOCK_SIZE_CHECK(X) \
if (((X) > PSTORAGE_MAX_BLOCK_SIZE) || ((X) < PSTORAGE_MIN_BLOCK_SIZE)) \
{ \
return NRF_ERROR_INVALID_PARAM; \
}
/**
* @brief Verifies block size requested by Application in registration API.
*/
#define BLOCK_COUNT_CHECK(COUNT, SIZE) \
if (((COUNT) == 0) || ((m_next_page_addr + ((COUNT) *(SIZE)) > PSTORAGE_DATA_END_ADDR))) \
{ \
return NRF_ERROR_INVALID_PARAM; \
}
/**
* @brief Verifies size parameter provided by application in API.
*/
#define SIZE_CHECK(ID, SIZE) \
if(((SIZE) == 0) || ((SIZE) > MODULE_BLOCK_SIZE(ID))) \
{ \
return NRF_ERROR_INVALID_PARAM; \
}
/**
* @brief Verifies offset parameter provided by application in API.
*/
#define OFFSET_CHECK(ID, OFFSET, SIZE) \
if(((SIZE) + (OFFSET)) > MODULE_BLOCK_SIZE(ID)) \
{ \
return NRF_ERROR_INVALID_PARAM; \
}
#ifdef PSTORAGE_RAW_MODE_ENABLE
/**
* @brief Verifies the module identifier supplied by the application is registered for raw mode.
*/
#define MODULE_RAW_ID_RANGE_CHECK(ID) \
if ((PSTORAGE_MAX_APPLICATIONS+1 != ((ID)->module_id)) || \
(m_raw_app_table.cb == NULL)) \
{ \
return NRF_ERROR_INVALID_PARAM; \
}
#endif // PSTORAGE_RAW_MODE_ENABLE
/**@} */
/**@brief Verify module's initialization status.
*
* @details Verify module's initialization status. Returns NRF_ERROR_INVALID_STATE in case a
* module API is called without initializing the module.
*/
#define VERIFY_MODULE_INITIALIZED() \
do \
{ \
if (!m_module_initialized) \
{ \
return NRF_ERROR_INVALID_STATE; \
} \
} while(0)
/**@brief Macro to fetch the block size registered for the module. */
#define MODULE_BLOCK_SIZE(ID) (m_app_table[(ID)->module_id].block_size)
/**@} */
/**
* @brief Application registration information.
*
* @details Define application specific information that application needs to maintain to be able
* to process requests from each one of them.
*/
typedef struct
{
pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
pstorage_block_t base_id; /**< Base block id assigned to the module */
pstorage_size_t block_size; /**< Size of block for the module */
pstorage_size_t block_count; /**< Number of block requested by application */
pstorage_size_t no_of_pages; /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
} pstorage_module_table_t;
#ifdef PSTORAGE_RAW_MODE_ENABLE
/**
* @brief Application registration information.
*
* @details Define application specific information that application registered for raw mode.
*/
typedef struct
{
pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
uint16_t no_of_pages; /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
} pstorage_raw_module_table_t;
#endif // PSTORAGE_RAW_MODE_ENABLE
/**
* @brief Defines command queue element.
*
* @details Defines command queue element. Each element encapsulates needed information to process
* a flash access command.
*/
typedef struct
{
uint8_t op_code; /**< Identifies flash access operation being queued. Element is free is op-code is INVALID_OPCODE */
pstorage_size_t size; /**< Identifies size in bytes requested for the operation. */
pstorage_size_t offset; /**< Offset requested by the application for access operation. */
pstorage_handle_t storage_addr; /**< Address/Identifier for persistent memory. */
uint8_t * p_data_addr; /**< Address/Identifier for data memory. This is assumed to be resident memory. */
} cmd_queue_element_t;
/**
* @brief Defines command queue, an element is free is op_code field is not invalid.
*
* @details Defines commands enqueued for flash access. At any point of time, this queue has one or
* more flash access operation pending if the count field is not zero. When the queue is
* not empty, the rp (read pointer) field points to the flash access command in progress
* or to requested next. The queue implements a simple first in first out algorithm.
* Data addresses are assumed to be resident.
*/
typedef struct
{
uint8_t rp; /**< Read pointer, pointing to flash access that is ongoing or to be requested next. */
uint8_t count; /**< Number of elements in the queue. */
bool flash_access; /**< Flag to ensure an flash event received is for an request issued by the module. */
cmd_queue_element_t cmd[PSTORAGE_CMD_QUEUE_SIZE]; /**< Array to maintain flash access operation details */
}cmd_queue_t;
static cmd_queue_t m_cmd_queue; /**< Flash operation request queue. */
static pstorage_module_table_t m_app_table[PSTORAGE_MAX_APPLICATIONS]; /**< Registered application information table. */
#ifdef PSTORAGE_RAW_MODE_ENABLE
static pstorage_raw_module_table_t m_raw_app_table; /**< Registered application information table for raw mode. */
#endif // PSTORAGE_RAW_MODE_ENABLE
static pstorage_size_t m_next_app_instance; /**< Points to the application module instance that can be allocated next */
static uint32_t m_next_page_addr; /**< Points to the flash address that can be allocated to a module next, this is needed as blocks of a module can span across flash pages. */
static bool m_module_initialized = false; /**< Flag for checking if module has been initialized. */
static pstorage_size_t m_round_val; /**< Round value for multiple round operations. For erase operations, the round value will contain current round counter which is identical to number of pages erased. For store operations, the round value contains current round of operation * SOC_MAX_WRITE_SIZE to ensure each store to the SoC Flash API is within the SoC limit. */
static uint32_t process_cmd(void);
static void app_notify (uint32_t reason);
/**
* @defgroup utility_functions Utility internal functions.
* @{
* @details Utility functions needed for interfacing with flash through SoC APIs.
* SoC APIs are non blocking and provide the result of flash access through an event.
*
* @note Only one flash access operation is permitted at a time by SoC. Hence a queue is
* maintained by this module.
*/
/**
* @brief Initializes command queue element.
*/
static void cmd_queue_init_element(uint32_t index)
{
// Internal function and checks on range of index can be avoided
m_cmd_queue.cmd[index].op_code = INVALID_OPCODE;
m_cmd_queue.cmd[index].size = 0;
m_cmd_queue.cmd[index].storage_addr.module_id = PSTORAGE_MAX_APPLICATIONS;
m_cmd_queue.cmd[index].storage_addr.block_id = 0;
m_cmd_queue.cmd[index].p_data_addr = NULL;
m_cmd_queue.cmd[index].offset = 0;
}
/**
* @brief Initializes command queue.
*/
static void cmd_queue_init (void)
{
uint32_t cmd_index;
m_round_val = 0;
m_cmd_queue.rp = 0;
m_cmd_queue.count = 0;
m_cmd_queue.flash_access = false;
for(cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; cmd_index++)
{
cmd_queue_init_element(cmd_index);
}
}
/**
* @brief Routine to enqueue a flash access operation.
*/
static uint32_t cmd_queue_enqueue(uint8_t opcode, pstorage_handle_t * p_storage_addr,uint8_t * p_data_addr, pstorage_size_t size, pstorage_size_t offset)
{
uint32_t retval;
uint8_t write_index = 0;
retval = NRF_ERROR_NO_MEM;
// Check if flash access is ongoing.
if ((m_cmd_queue.flash_access == false) && (m_cmd_queue.count == 0))
{
m_cmd_queue.rp = 0;
m_cmd_queue.cmd[m_cmd_queue.rp].op_code = opcode;
m_cmd_queue.cmd[m_cmd_queue.rp].p_data_addr = p_data_addr;
m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr = (*p_storage_addr);
m_cmd_queue.cmd[m_cmd_queue.rp].size = size;
m_cmd_queue.cmd[m_cmd_queue.rp].offset = offset;
m_cmd_queue.count++;
retval = process_cmd();
if ((retval == NRF_SUCCESS) || (retval == NRF_ERROR_BUSY))
{
// In case of busy error code, it is possible to attempt to access flash
retval = NRF_SUCCESS;
}
}
else if (m_cmd_queue.count != PSTORAGE_CMD_QUEUE_SIZE)
{
// Enqueue the command if it is queue is not full
write_index = m_cmd_queue.rp + m_cmd_queue.count;
if (write_index >= PSTORAGE_CMD_QUEUE_SIZE)
{
write_index -= PSTORAGE_CMD_QUEUE_SIZE;
}
m_cmd_queue.cmd[write_index].op_code = opcode;
m_cmd_queue.cmd[write_index].p_data_addr = p_data_addr;
m_cmd_queue.cmd[write_index].storage_addr = (*p_storage_addr);
m_cmd_queue.cmd[write_index].size = size;
m_cmd_queue.cmd[write_index].offset = offset;
m_cmd_queue.count++;
retval = NRF_SUCCESS;
}
return retval;
}
/**
* @brief Dequeues a command element.
*/
static uint32_t cmd_queue_dequeue(void)
{
uint32_t retval;
cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
// Update count and read pointer to process any queued requests
if(m_round_val >= p_cmd->size)
{
// Initialize/free the element as it is now processed.
cmd_queue_init_element(m_cmd_queue.rp);
m_round_val = 0;
m_cmd_queue.count--;
m_cmd_queue.rp++;
}
retval = NRF_SUCCESS;
// If any flash operation is enqueued, schedule
if (m_cmd_queue.count)
{
retval = process_cmd();
if (retval != NRF_SUCCESS)
{
// Flash could be accessed by modules other than Bond Manager, hence a busy error is
// acceptable, but any other error needs to be indicated to the bond manager
if (retval != NRF_ERROR_BUSY)
{
app_notify (retval);
}
else
{
// In case of busy next trigger will be a success or a failure event
}
}
}
else
{
// No flash access request pending
}
return retval;
}
/**
* @brief Routine to notify application of any errors.
*/
static void app_notify (uint32_t result)
{
pstorage_ntf_cb_t ntf_cb;
uint8_t op_code = m_cmd_queue.cmd[m_cmd_queue.rp].op_code;
#ifdef PSTORAGE_RAW_MODE_ENABLE
if(m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr.module_id == (PSTORAGE_MAX_APPLICATIONS + 1))
{
ntf_cb = m_raw_app_table.cb;
}
else
#endif // PSTORAGE_RAW_MODE_ENABLE
{
ntf_cb = m_app_table[m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr.module_id].cb;
}
// Indicate result to client.
// For PSTORAGE_CLEAR_OP_CODE no size is returned as the size field is used only internally
// for clients registering multiple pages.
ntf_cb(&m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr,
op_code,
result,
m_cmd_queue.cmd[m_cmd_queue.rp].p_data_addr,
op_code == PSTORAGE_CLEAR_OP_CODE ? 0 : m_cmd_queue.cmd[m_cmd_queue.rp].size);
}
/**
* @brief Handles Flash Access Result Events.
*/
void pstorage_sys_event_handler (uint32_t sys_evt)
{
uint32_t retval;
retval = NRF_SUCCESS;
// Its possible the flash access was not initiated by bond manager, hence
// event is processed only if the event triggered was for an operation requested by the
// bond manager.
if (m_cmd_queue.flash_access == true)
{
cmd_queue_element_t * p_cmd;
m_cmd_queue.flash_access = false;
switch (sys_evt)
{
case NRF_EVT_FLASH_OPERATION_SUCCESS:
p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
if ((p_cmd->op_code != PSTORAGE_CLEAR_OP_CODE) || (m_round_val >= p_cmd->size))
{
app_notify(retval);
}
// Schedule any queued flash access operations
retval = cmd_queue_dequeue ();
if (retval != NRF_SUCCESS)
{
app_notify(retval);
}
break;
case NRF_EVT_FLASH_OPERATION_ERROR:
app_notify(NRF_ERROR_TIMEOUT);
break;
default:
// No implementation needed.
break;
}
}
}
/**
* @brief Routine called to actually issue the flash access request to the SoftDevice.
*/
static uint32_t process_cmd(void)
{
uint32_t retval;
uint32_t storage_addr;
cmd_queue_element_t * p_cmd;
retval = NRF_ERROR_FORBIDDEN;
p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
storage_addr = p_cmd->storage_addr.block_id;
if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE)
{
// Calculate page number before copy.
uint32_t page_number;
page_number = ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) +
m_round_val);
retval = sd_flash_page_erase(page_number);
if (NRF_SUCCESS == retval)
{
m_round_val++;
}
}
else if (p_cmd->op_code == PSTORAGE_STORE_OP_CODE)
{
uint32_t size;
uint8_t * p_data_addr = p_cmd->p_data_addr;
p_data_addr += m_round_val;
storage_addr += (p_cmd->offset + m_round_val);
size = p_cmd->size - m_round_val;
if (size < SOC_MAX_WRITE_SIZE)
{
retval = sd_flash_write(((uint32_t *)storage_addr),
(uint32_t *)p_data_addr,
size / sizeof(uint32_t));
}
else
{
retval = sd_flash_write(((uint32_t *)storage_addr),
(uint32_t *)p_data_addr,
SOC_MAX_WRITE_SIZE / sizeof(uint32_t));
}
if (retval == NRF_SUCCESS)
{
m_round_val += SOC_MAX_WRITE_SIZE;
}
}
else
{
// Should never reach here.
}
if (retval == NRF_SUCCESS)
{
m_cmd_queue.flash_access = true;
}
return retval;
}
/** @} */
/**
* @brief Module initialization routine to be called once by the application.
*/
uint32_t pstorage_init(void)
{
unsigned int index;
cmd_queue_init();
m_next_app_instance = 0;
m_next_page_addr = PSTORAGE_DATA_START_ADDR;
m_round_val = 0;
for(index = 0; index < PSTORAGE_MAX_APPLICATIONS; index++)
{
m_app_table[index].cb = NULL;
m_app_table[index].block_size = 0;
m_app_table[index].no_of_pages = 0;
m_app_table[index].block_count = 0;
}
#ifdef PSTORAGE_RAW_MODE_ENABLE
m_raw_app_table.cb = NULL;
m_raw_app_table.no_of_pages = 0;
#endif //PSTORAGE_RAW_MODE_ENABLE
m_module_initialized = true;
return NRF_SUCCESS;
}
/**
* @brief Registration routine to request persistent memory of certain sizes based on
* application module requirements.
*/
uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
pstorage_handle_t * p_block_id)
{
uint16_t page_count;
uint32_t total_size;
VERIFY_MODULE_INITIALIZED();
NULL_PARAM_CHECK(p_module_param);
NULL_PARAM_CHECK(p_block_id);
NULL_PARAM_CHECK(p_module_param->cb);
BLOCK_SIZE_CHECK(p_module_param->block_size);
BLOCK_COUNT_CHECK(p_module_param->block_count, p_module_param->block_size);
if (m_next_app_instance == PSTORAGE_MAX_APPLICATIONS)
{
return NRF_ERROR_NO_MEM;
}
p_block_id->module_id = m_next_app_instance;
p_block_id->block_id = m_next_page_addr;
m_app_table[m_next_app_instance].base_id = p_block_id->block_id;
m_app_table[m_next_app_instance].cb = p_module_param->cb;
m_app_table[m_next_app_instance].block_size = p_module_param->block_size;
m_app_table[m_next_app_instance].block_count = p_module_param->block_count;
// Calculate number of flash pages allocated for the device.
page_count = 0;
total_size = p_module_param->block_size * p_module_param->block_count;
do
{
page_count++;
if (total_size > PSTORAGE_FLASH_PAGE_SIZE)
{
total_size -= PSTORAGE_FLASH_PAGE_SIZE;
}
else
{
total_size = 0;
}
m_next_page_addr += PSTORAGE_FLASH_PAGE_SIZE;
}while(total_size >= PSTORAGE_FLASH_PAGE_SIZE);
m_app_table[m_next_app_instance].no_of_pages = page_count;
m_next_app_instance++;
return NRF_SUCCESS;
}
/**
* @brief API to get the next block identifier.
*/
uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
pstorage_size_t block_num,
pstorage_handle_t * p_block_id)
{
pstorage_handle_t temp_id;
VERIFY_MODULE_INITIALIZED();
NULL_PARAM_CHECK(p_base_id);
NULL_PARAM_CHECK(p_block_id);
MODULE_ID_RANGE_CHECK(p_base_id);
temp_id = (*p_base_id);
temp_id.block_id += (block_num * MODULE_BLOCK_SIZE(p_base_id));
BLOCK_ID_RANGE_CHECK(&temp_id);
(*p_block_id) = temp_id;
return NRF_SUCCESS;
}
/**
* @brief API to store data persistently.
*/
uint32_t pstorage_store(pstorage_handle_t * p_dest,
uint8_t * p_src,
pstorage_size_t size,
pstorage_size_t offset)
{
VERIFY_MODULE_INITIALIZED();
NULL_PARAM_CHECK(p_src);
NULL_PARAM_CHECK(p_dest);
MODULE_ID_RANGE_CHECK (p_dest);
BLOCK_ID_RANGE_CHECK(p_dest);
SIZE_CHECK(p_dest,size);
OFFSET_CHECK(p_dest,offset,size);
// Verify word alignment.
if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
{
return NRF_ERROR_INVALID_ADDR;
}
return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
}
/**
* @brief API to load data from persistent memory.
*/
uint32_t pstorage_load(uint8_t * p_dest,
pstorage_handle_t * p_src,
pstorage_size_t size,
pstorage_size_t offset)
{
VERIFY_MODULE_INITIALIZED();
NULL_PARAM_CHECK(p_src);
NULL_PARAM_CHECK(p_dest);
MODULE_ID_RANGE_CHECK (p_src);
BLOCK_ID_RANGE_CHECK(p_src);
SIZE_CHECK(p_src,size);
OFFSET_CHECK(p_src,offset,size);
// Verify word alignment.
if ((!is_word_aligned (p_dest)) || (!is_word_aligned (p_dest + offset)))
{
return NRF_ERROR_INVALID_ADDR;
}
memcpy (p_dest, (((uint8_t *)p_src->block_id) + offset), size);
return NRF_SUCCESS;
}
/**
* @brief API to clear data in blocks of persistent memory.
*/
uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
{
uint32_t retval;
uint32_t pages;
VERIFY_MODULE_INITIALIZED();
NULL_PARAM_CHECK(p_dest);
MODULE_ID_RANGE_CHECK(p_dest);
BLOCK_ID_RANGE_CHECK(p_dest);
pages = m_app_table[p_dest->module_id].no_of_pages;
retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , pages , 0);
return retval;
}
#ifdef PSTORAGE_RAW_MODE_ENABLE
/**
* @brief Registration routine to request persistent memory of certain sizes based on
* application module requirements.
*/
uint32_t pstorage_raw_register(pstorage_module_param_t * p_module_param,
pstorage_handle_t * p_block_id)
{
VERIFY_MODULE_INITIALIZED();
NULL_PARAM_CHECK(p_module_param);
NULL_PARAM_CHECK(p_block_id);
NULL_PARAM_CHECK(p_module_param->cb);
if (m_raw_app_table.cb != NULL)
{
return NRF_ERROR_NO_MEM;
}
p_block_id->module_id = PSTORAGE_MAX_APPLICATIONS + 1;
m_raw_app_table.cb = p_module_param->cb;
return NRF_SUCCESS;
}
/**
* @brief API to store data persistently.
*/
uint32_t pstorage_raw_store(pstorage_handle_t * p_dest,
uint8_t * p_src,
uint32_t size,
uint32_t offset)
{
VERIFY_MODULE_INITIALIZED();
NULL_PARAM_CHECK(p_src);
NULL_PARAM_CHECK(p_dest);
MODULE_RAW_ID_RANGE_CHECK(p_dest);
// Verify word alignment.
if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
{
return NRF_ERROR_INVALID_ADDR;
}
return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
}
/**
* @brief API to clear data in blocks of persistent memory.
*/
uint32_t pstorage_raw_clear(pstorage_handle_t * p_dest, uint32_t size)
{
uint32_t retval;
uint32_t pages;
VERIFY_MODULE_INITIALIZED();
NULL_PARAM_CHECK(p_dest);
MODULE_RAW_ID_RANGE_CHECK(p_dest);
retval = NRF_SUCCESS;
pages = CEIL_DIV(size, PSTORAGE_FLASH_PAGE_SIZE);
retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , pages, 0);
return retval;
}
#endif // PSTORAGE_RAW_MODE_ENABLE

View File

@ -1,624 +0,0 @@
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include "ble_advdata.h"
#include "nordic_common.h"
#include "nrf_error.h"
#include "ble_gap.h"
#include "ble_srv_common.h"
#include "app_util.h"
// Offset from where advertisement data other than flags information can start.
#define ADV_FLAG_OFFSET 2
// Offset for Advertising Data.
// Offset is 2 as each Advertising Data contain 1 octet of Adveritising Data Type and
// one octet Advertising Data Length.
#define ADV_DATA_OFFSET 2
// NOTE: For now, Security Manager TK Value and Security Manager Out of Band Flags (OOB) are omitted
// from the advertising data.
static uint32_t name_encode(const ble_advdata_t * p_advdata,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
uint32_t err_code;
uint16_t rem_adv_data_len;
uint16_t actual_length;
uint8_t adv_data_format;
uint8_t adv_offset;
adv_offset = *p_len;
// Check for buffer overflow.
if ((adv_offset + ADV_DATA_OFFSET > BLE_GAP_ADV_MAX_SIZE) ||
((p_advdata->short_name_len + ADV_DATA_OFFSET) > BLE_GAP_ADV_MAX_SIZE))
{
return NRF_ERROR_DATA_SIZE;
}
actual_length = rem_adv_data_len = (BLE_GAP_ADV_MAX_SIZE - adv_offset - ADV_FLAG_OFFSET);
// Get GAP device name and length
err_code = sd_ble_gap_device_name_get(&p_encoded_data[adv_offset + ADV_DATA_OFFSET],
&actual_length);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Check if device internd to use short name and it can fit available data size.
if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len))
{
// Complete device name can fit, setting Complete Name in Adv Data.
adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
rem_adv_data_len = actual_length;
}
else
{
// Else short name needs to be used. Or application has requested use of short name.
adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
// If application has set a preference on the short name size, it needs to be considered,
// else fit what can be fit.
if ((p_advdata->short_name_len != 0) && (p_advdata->short_name_len <= rem_adv_data_len))
{
// Short name fits available size.
rem_adv_data_len = p_advdata->short_name_len;
}
// Else whatever can fit the data buffer will be packed.
else
{
rem_adv_data_len = actual_length;
}
}
// Complete name field in encoded data.
p_encoded_data[adv_offset++] = rem_adv_data_len + 1;
p_encoded_data[adv_offset++] = adv_data_format;
(*p_len) += (rem_adv_data_len + ADV_DATA_OFFSET);
return NRF_SUCCESS;
}
static uint32_t appearance_encode(uint8_t * p_encoded_data, uint8_t * p_len)
{
uint32_t err_code;
uint16_t appearance;
// Check for buffer overflow.
if ((*p_len) + 4 > BLE_GAP_ADV_MAX_SIZE)
{
return NRF_ERROR_DATA_SIZE;
}
// Get GAP appearance field.
err_code = sd_ble_gap_appearance_get(&appearance);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Encode Length, AD Type and Appearance.
p_encoded_data[(*p_len)++] = 3;
p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_APPEARANCE;
(*p_len) += uint16_encode(appearance, &p_encoded_data[*p_len]);
return NRF_SUCCESS;
}
static uint32_t uint8_array_encode(const uint8_array_t * p_uint8_array,
uint8_t adv_type,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
// Check parameter consistency.
if (p_uint8_array->p_data == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
// Check for buffer overflow.
if ((*p_len) + ADV_DATA_OFFSET + p_uint8_array->size > BLE_GAP_ADV_MAX_SIZE)
{
return NRF_ERROR_DATA_SIZE;
}
// Encode Length and AD Type.
p_encoded_data[(*p_len)++] = 1 + p_uint8_array->size;
p_encoded_data[(*p_len)++] = adv_type;
// Encode array.
memcpy(&p_encoded_data[*p_len], p_uint8_array->p_data, p_uint8_array->size);
(*p_len) += p_uint8_array->size;
return NRF_SUCCESS;
}
static uint32_t tx_power_level_encode(int8_t tx_power_level,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
// Check for buffer overflow.
if ((*p_len) + 3 > BLE_GAP_ADV_MAX_SIZE)
{
return NRF_ERROR_DATA_SIZE;
}
// Encode TX Power Level.
p_encoded_data[(*p_len)++] = 2;
p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL;
p_encoded_data[(*p_len)++] = (uint8_t)tx_power_level;
return NRF_SUCCESS;
}
static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list,
uint8_t adv_type,
uint8_t uuid_size,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
int i;
bool is_heading_written = false;
uint8_t start_pos = *p_len;
for (i = 0; i < p_uuid_list->uuid_cnt; i++)
{
uint32_t err_code;
uint8_t encoded_size;
ble_uuid_t uuid = p_uuid_list->p_uuids[i];
// Find encoded uuid size.
err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Check size.
if (encoded_size == uuid_size)
{
uint8_t heading_bytes = (is_heading_written) ? 0 : 2;
// Check for buffer overflow
if (*p_len + encoded_size + heading_bytes > BLE_GAP_ADV_MAX_SIZE)
{
return NRF_ERROR_DATA_SIZE;
}
if (!is_heading_written)
{
// Write AD structure heading.
(*p_len)++;
p_encoded_data[(*p_len)++] = adv_type;
is_heading_written = true;
}
// Write UUID.
err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_len]);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
(*p_len) += encoded_size;
}
}
if (is_heading_written)
{
// Write length.
p_encoded_data[start_pos] = (*p_len) - (start_pos + 1);
}
return NRF_SUCCESS;
}
static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list,
uint8_t adv_type_16,
uint8_t adv_type_128,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
uint32_t err_code;
// Encode 16 bit UUIDs.
err_code = uuid_list_sized_encode(p_uuid_list,
adv_type_16,
sizeof(uint16_le_t),
p_encoded_data,
p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Encode 128 bit UUIDs.
err_code = uuid_list_sized_encode(p_uuid_list,
adv_type_128,
sizeof(ble_uuid128_t),
p_encoded_data,
p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
return NRF_SUCCESS;
}
static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int)
{
// Check Minimum Connection Interval.
if ((p_conn_int->min_conn_interval < 0x0006) ||
(
(p_conn_int->min_conn_interval > 0x0c80) &&
(p_conn_int->min_conn_interval != 0xffff)
)
)
{
return NRF_ERROR_INVALID_PARAM;
}
// Check Maximum Connection Interval.
if ((p_conn_int->max_conn_interval < 0x0006) ||
(
(p_conn_int->max_conn_interval > 0x0c80) &&
(p_conn_int->max_conn_interval != 0xffff)
)
)
{
return NRF_ERROR_INVALID_PARAM;
}
// Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval.
if ((p_conn_int->min_conn_interval != 0xffff) &&
(p_conn_int->max_conn_interval != 0xffff) &&
(p_conn_int->min_conn_interval > p_conn_int->max_conn_interval)
)
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
uint32_t err_code;
// Check for buffer overflow.
if ((*p_len) + ADV_DATA_OFFSET + 2 * sizeof(uint16_le_t) > BLE_GAP_ADV_MAX_SIZE)
{
return NRF_ERROR_DATA_SIZE;
}
// Check parameters.
err_code = conn_int_check(p_conn_int);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Encode Length and AD Type.
p_encoded_data[(*p_len)++] = 1 + 2 * sizeof(uint16_le_t);
p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE;
// Encode Minimum and Maximum Connection Intervals.
(*p_len) += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_len]);
(*p_len) += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_len]);
return NRF_SUCCESS;
}
static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
uint8_t data_size = sizeof(uint16_le_t) + p_manuf_sp_data->data.size;
// Check for buffer overflow.
if ((*p_len) + ADV_DATA_OFFSET + data_size > BLE_GAP_ADV_MAX_SIZE)
{
return NRF_ERROR_DATA_SIZE;
}
// Encode Length and AD Type.
p_encoded_data[(*p_len)++] = 1 + data_size;
p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
// Encode Company Identifier.
(*p_len) += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_len]);
// Encode additional manufacturer specific data.
if (p_manuf_sp_data->data.size > 0)
{
if (p_manuf_sp_data->data.p_data == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
memcpy(&p_encoded_data[*p_len], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size);
(*p_len) += p_manuf_sp_data->data.size;
}
return NRF_SUCCESS;
}
static uint32_t service_data_encode(const ble_advdata_t * p_advdata,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
uint8_t i;
// Check parameter consistency.
if (p_advdata->p_service_data_array == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
for (i = 0; i < p_advdata->service_data_count; i++)
{
ble_advdata_service_data_t * p_service_data;
uint8_t data_size;
p_service_data = &p_advdata->p_service_data_array[i];
data_size = sizeof(uint16_le_t) + p_service_data->data.size;
// Encode Length and AD Type.
p_encoded_data[(*p_len)++] = 1 + data_size;
p_encoded_data[(*p_len)++] = BLE_GAP_AD_TYPE_SERVICE_DATA;
// Encode service UUID.
(*p_len) += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_len]);
// Encode additional service data.
if (p_service_data->data.size > 0)
{
if (p_service_data->data.p_data == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
memcpy(&p_encoded_data[*p_len], p_service_data->data.p_data, p_service_data->data.size);
(*p_len) += p_service_data->data.size;
}
}
return NRF_SUCCESS;
}
static uint32_t adv_data_encode(const ble_advdata_t * p_advdata,
uint8_t * p_encoded_data,
uint8_t * p_len)
{
uint32_t err_code = NRF_SUCCESS;
*p_len = 0;
// Encode name.
if (p_advdata->name_type != BLE_ADVDATA_NO_NAME)
{
err_code = name_encode(p_advdata, p_encoded_data, p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode appearance.
if (p_advdata->include_appearance)
{
err_code = appearance_encode(p_encoded_data, p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode flags.
if (p_advdata->flags.size > 0)
{
err_code = uint8_array_encode(&p_advdata->flags,
BLE_GAP_AD_TYPE_FLAGS,
p_encoded_data,
p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode TX power level.
if (p_advdata->p_tx_power_level != NULL)
{
err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, p_encoded_data, p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode 'more available' uuid list.
if (p_advdata->uuids_more_available.uuid_cnt > 0)
{
err_code = uuid_list_encode(&p_advdata->uuids_more_available,
BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,
BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE,
p_encoded_data,
p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode 'complete' uuid list.
if (p_advdata->uuids_complete.uuid_cnt > 0)
{
err_code = uuid_list_encode(&p_advdata->uuids_complete,
BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
p_encoded_data,
p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode 'solicited service' uuid list.
if (p_advdata->uuids_solicited.uuid_cnt > 0)
{
err_code = uuid_list_encode(&p_advdata->uuids_solicited,
BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT,
BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT,
p_encoded_data,
p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode Slave Connection Interval Range.
if (p_advdata->p_slave_conn_int != NULL)
{
err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode Manufacturer Specific Data.
if (p_advdata->p_manuf_specific_data != NULL)
{
err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data,
p_encoded_data,
p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
// Encode Service Data.
if (p_advdata->service_data_count > 0)
{
err_code = service_data_encode(p_advdata, p_encoded_data, p_len);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
return err_code;
}
static uint32_t advdata_check(const ble_advdata_t * p_advdata)
{
// Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set.
if ((p_advdata->flags.size == 0) ||
(p_advdata->flags.p_data == NULL) ||
((p_advdata->flags.p_data[0] & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0)
)
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
static uint32_t srdata_check(const ble_advdata_t * p_srdata)
{
// Flags shall not be included in the scan response data.
if (p_srdata->flags.size > 0)
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata)
{
uint32_t err_code;
uint8_t len_advdata = 0;
uint8_t len_srdata = 0;
uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE];
uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE];
uint8_t * p_encoded_advdata;
uint8_t * p_encoded_srdata;
// Encode advertising data (if supplied).
if (p_advdata != NULL)
{
err_code = advdata_check(p_advdata);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
p_encoded_advdata = encoded_advdata;
}
else
{
p_encoded_advdata = NULL;
}
// Encode scan response data (if supplied).
if (p_srdata != NULL)
{
err_code = srdata_check(p_srdata);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
p_encoded_srdata = encoded_srdata;
}
else
{
p_encoded_srdata = NULL;
}
// Pass encoded advertising data and/or scan response data to the stack.
return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata);
}

View File

@ -1,21 +0,0 @@
#include "ble_advdata_parser.h"
uint32_t ble_advdata_parser_field_find(uint8_t type, uint8_t * p_advdata, uint8_t * len, uint8_t ** pp_field_data)
{
uint32_t index = 0;
while (index < *len)
{
uint8_t field_length = p_advdata[index];
uint8_t field_type = p_advdata[index+1];
if (field_type == type)
{
*pp_field_data = &p_advdata[index+2];
*len = field_length-1;
return NRF_SUCCESS;
}
index += field_length+1;
}
return NRF_ERROR_NOT_FOUND;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,322 +0,0 @@
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include "ble_conn_params.h"
#include <stdlib.h>
#include "nordic_common.h"
#include "ble_hci.h"
#include "app_timer.h"
#include "ble_srv_common.h"
#include "app_util.h"
static ble_conn_params_init_t m_conn_params_config; /**< Configuration as specified by the application. */
static ble_gap_conn_params_t m_preferred_conn_params; /**< Connection parameters preferred by the application. */
static uint8_t m_update_count; /**< Number of Connection Parameter Update messages that has currently been sent. */
static uint16_t m_conn_handle; /**< Current connection handle. */
static ble_gap_conn_params_t m_current_conn_params; /**< Connection parameters received in the most recent Connect event. */
static app_timer_id_t m_conn_params_timer_id; /**< Connection parameters timer. */
static bool m_change_param = false;
static bool is_conn_params_ok(ble_gap_conn_params_t * p_conn_params)
{
// Check if interval is within the acceptable range.
// NOTE: Using max_conn_interval in the received event data because this contains
// the client's connection interval.
if (
(p_conn_params->max_conn_interval >= m_preferred_conn_params.min_conn_interval)
&&
(p_conn_params->max_conn_interval <= m_preferred_conn_params.max_conn_interval)
)
{
return true;
}
else
{
return false;
}
}
static void update_timeout_handler(void * p_context)
{
UNUSED_PARAMETER(p_context);
if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
{
// Check if we have reached the maximum number of attempts
m_update_count++;
if (m_update_count <= m_conn_params_config.max_conn_params_update_count)
{
uint32_t err_code;
// Parameters are not ok, send connection parameters update request.
err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_preferred_conn_params);
if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
{
m_conn_params_config.error_handler(err_code);
}
}
else
{
m_update_count = 0;
// Negotiation failed, disconnect automatically if this has been configured
if (m_conn_params_config.disconnect_on_fail)
{
uint32_t err_code;
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
{
m_conn_params_config.error_handler(err_code);
}
}
// Notify the application that the procedure has failed
if (m_conn_params_config.evt_handler != NULL)
{
ble_conn_params_evt_t evt;
evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED;
m_conn_params_config.evt_handler(&evt);
}
}
}
}
uint32_t ble_conn_params_init(const ble_conn_params_init_t * p_init)
{
uint32_t err_code;
m_conn_params_config = *p_init;
m_change_param = false;
if (p_init->p_conn_params != NULL)
{
m_preferred_conn_params = *p_init->p_conn_params;
// Set the connection params in stack
err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
else
{
// Fetch the connection params from stack
err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
m_conn_handle = BLE_CONN_HANDLE_INVALID;
m_update_count = 0;
return app_timer_create(&m_conn_params_timer_id,
APP_TIMER_MODE_SINGLE_SHOT,
update_timeout_handler);
}
uint32_t ble_conn_params_stop(void)
{
return app_timer_stop(m_conn_params_timer_id);
}
static void conn_params_negotiation(void)
{
// Start negotiation if the received connection parameters are not acceptable
if (!is_conn_params_ok(&m_current_conn_params))
{
uint32_t err_code;
uint32_t timeout_ticks;
if (m_change_param)
{
// Notify the application that the procedure has failed
if (m_conn_params_config.evt_handler != NULL)
{
ble_conn_params_evt_t evt;
evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED;
m_conn_params_config.evt_handler(&evt);
}
}
else
{
if (m_update_count == 0)
{
// First connection parameter update
timeout_ticks = m_conn_params_config.first_conn_params_update_delay;
}
else
{
timeout_ticks = m_conn_params_config.next_conn_params_update_delay;
}
err_code = app_timer_start(m_conn_params_timer_id, timeout_ticks, NULL);
if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
{
m_conn_params_config.error_handler(err_code);
}
}
}
else
{
// Notify the application that the procedure has succeded
if (m_conn_params_config.evt_handler != NULL)
{
ble_conn_params_evt_t evt;
evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED;
m_conn_params_config.evt_handler(&evt);
}
}
m_change_param = false;
}
static void on_connect(ble_evt_t * p_ble_evt)
{
// Save connection parameters
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
m_current_conn_params = p_ble_evt->evt.gap_evt.params.connected.conn_params;
m_update_count = 0; // Connection parameter negotiation should re-start every connection
// Check if we shall handle negotiation on connect
if (m_conn_params_config.start_on_notify_cccd_handle == BLE_GATT_HANDLE_INVALID)
{
conn_params_negotiation();
}
}
static void on_disconnect(ble_evt_t * p_ble_evt)
{
uint32_t err_code;
m_conn_handle = BLE_CONN_HANDLE_INVALID;
// Stop timer if running
m_update_count = 0; // Connection parameters updates should happen during every connection
err_code = app_timer_stop(m_conn_params_timer_id);
if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
{
m_conn_params_config.error_handler(err_code);
}
}
static void on_write(ble_evt_t * p_ble_evt)
{
ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
// Check if this the correct CCCD
if (
(p_evt_write->handle == m_conn_params_config.start_on_notify_cccd_handle)
&&
(p_evt_write->len == 2)
)
{
// Check if this is a 'start notification'
if (ble_srv_is_notification_enabled(p_evt_write->data))
{
// Do connection parameter negotiation if necessary
conn_params_negotiation();
}
else
{
uint32_t err_code;
// Stop timer if running
err_code = app_timer_stop(m_conn_params_timer_id);
if ((err_code != NRF_SUCCESS) && (m_conn_params_config.error_handler != NULL))
{
m_conn_params_config.error_handler(err_code);
}
}
}
}
static void on_conn_params_update(ble_evt_t * p_ble_evt)
{
// Copy the parameters
m_current_conn_params = p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params;
conn_params_negotiation();
}
void ble_conn_params_on_ble_evt(ble_evt_t * p_ble_evt)
{
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
on_connect(p_ble_evt);
break;
case BLE_GAP_EVT_DISCONNECTED:
on_disconnect(p_ble_evt);
break;
case BLE_GATTS_EVT_WRITE:
on_write(p_ble_evt);
break;
case BLE_GAP_EVT_CONN_PARAM_UPDATE:
on_conn_params_update(p_ble_evt);
break;
default:
// No implementation needed.
break;
}
}
uint32_t ble_conn_params_change_conn_params(ble_gap_conn_params_t *new_params)
{
uint32_t err_code;
m_preferred_conn_params = *new_params;
// Set the connection params in stack
err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
if (err_code == NRF_SUCCESS)
{
if (!is_conn_params_ok(&m_current_conn_params))
{
m_change_param = true;
err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_preferred_conn_params);
m_update_count = 1;
}
else
{
// Notify the application that the procedure has succeded
if (m_conn_params_config.evt_handler != NULL)
{
ble_conn_params_evt_t evt;
evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED;
m_conn_params_config.evt_handler(&evt);
}
err_code = NRF_SUCCESS;
}
}
return err_code;
}

View File

@ -1,55 +0,0 @@
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include "ble_debug_assert_handler.h"
#include <string.h>
#include "nrf51.h"
#include "ble_error_log.h"
#include "nordic_common.h"
#define MAX_LENGTH_FILENAME 128 /**< Max length of filename to copy for the debug error handlier. */
// WARNING - DO NOT USE THIS FUNCTION IN END PRODUCT. - WARNING
// WARNING - FOR DEBUG PURPOSES ONLY. - WARNING
void ble_debug_assert_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
// Copying parameters to static variables because parameters may not be accessible in debugger.
static volatile uint8_t s_file_name[MAX_LENGTH_FILENAME];
static volatile uint16_t s_line_num;
static volatile uint32_t s_error_code;
strncpy((char *)s_file_name, (const char *)p_file_name, MAX_LENGTH_FILENAME - 1);
s_file_name[MAX_LENGTH_FILENAME - 1] = '\0';
s_line_num = line_num;
s_error_code = error_code;
UNUSED_VARIABLE(s_file_name);
UNUSED_VARIABLE(s_line_num);
UNUSED_VARIABLE(s_error_code);
// WARNING: The PRIMASK register is set to disable ALL interrups during writing the error log.
//
// Do not use __disable_irq() in normal operation.
__disable_irq();
// This function will write error code, filename, and line number to the flash.
// In addition, the Cortex-M0 stack memory will also be written to the flash.
//(void) ble_error_log_write(error_code, p_file_name, line_num);
// For debug purposes, this function never returns.
// Attach a debugger for tracing the error cause.
for (;;)
{
// Do nothing.
}
}

View File

@ -1,61 +0,0 @@
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <nrf51.h>
#include "ble_error_log.h"
#include "app_util.h"
#include "app_error.h"
#include "nrf_gpio.h"
#include "pstorage.h"
// Made static to avoid the error_log to go on the stack.
static ble_error_log_data_t m_ble_error_log; /**< . */
//lint -esym(526,__Vectors)
extern uint32_t * __Vectors; /**< The initialization vector holds the address to __initial_sp that will be used when fetching the stack. */
static void fetch_stack(ble_error_log_data_t * error_log)
{
// KTOWN: Temporarily removed 06022014
/*
uint32_t * p_stack;
uint32_t * initial_sp;
uint32_t length;
initial_sp = (uint32_t *) __Vectors;
p_stack = (uint32_t *) GET_SP();
length = ((uint32_t) initial_sp) - ((uint32_t) p_stack);
memcpy(error_log->stack_info,
p_stack,
(length > STACK_DUMP_LENGTH) ? STACK_DUMP_LENGTH : length);
*/
}
uint32_t ble_error_log_write(uint32_t err_code, const uint8_t * p_message, uint16_t line_number)
{
m_ble_error_log.failure = true;
m_ble_error_log.err_code = err_code;
m_ble_error_log.line_number = line_number;
strncpy((char *)m_ble_error_log.message, (const char *)p_message, ERROR_MESSAGE_LENGTH - 1);
m_ble_error_log.message[ERROR_MESSAGE_LENGTH - 1] = '\0';
fetch_stack(&m_ble_error_log);
// Write to flash removed, to be redone.
return NRF_SUCCESS;
}

View File

@ -1,41 +0,0 @@
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
/* Attention!
* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile
* qualification listings, this section of source code must not be modified.
*/
#include "ble_srv_common.h"
#include <string.h>
#include "nordic_common.h"
#include "app_error.h"
uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer,
const ble_srv_report_ref_t * p_report_ref)
{
uint8_t len = 0;
p_encoded_buffer[len++] = p_report_ref->report_id;
p_encoded_buffer[len++] = p_report_ref->report_type;
APP_ERROR_CHECK_BOOL(len == BLE_SRV_ENCODED_REPORT_REF_LEN);
return len;
}
void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii)
{
p_utf8->length = (uint16_t)strlen(p_ascii);
p_utf8->p_str = (uint8_t *)p_ascii;
}

View File

@ -1,35 +0,0 @@
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
/** @cond To make doxygen skip this file */
/** @file
*
* @defgroup ble_sdk_app_gls_bondmngr_cfg GLS Bond Manager Configuration
* @{
* @ingroup ble_sdk_app_gls
* @brief Definition of bond manager configurable parameters
*/
#ifndef BLE_BONDMNGR_CFG_H__
#define BLE_BONDMNGR_CFG_H__
/**@brief Number of CCCDs used in the GLS application. */
#define BLE_BONDMNGR_CCCD_COUNT 2
/**@brief Maximum number of bonded centrals. */
#define BLE_BONDMNGR_MAX_BONDED_CENTRALS 7
#endif // BLE_BONDMNGR_CFG_H__
/** @} */
/** @endcond */

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