]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
bringing port of up-to-date bluetooth interface and implementation to
authorayer1 <ayer1>
Fri, 4 Sep 2009 18:02:02 +0000 (18:02 +0000)
committerayer1 <ayer1>
Fri, 4 Sep 2009 18:02:02 +0000 (18:02 +0000)
tos-2.x

tos/platforms/shimmer/chips/bluetooth/Bluetooth.nc [new file with mode: 0644]
tos/platforms/shimmer/chips/bluetooth/RovingNetworks.h [new file with mode: 0644]
tos/platforms/shimmer/chips/bluetooth/RovingNetworksC.nc [new file with mode: 0644]
tos/platforms/shimmer/chips/bluetooth/RovingNetworksP.nc [new file with mode: 0644]

diff --git a/tos/platforms/shimmer/chips/bluetooth/Bluetooth.nc b/tos/platforms/shimmer/chips/bluetooth/Bluetooth.nc
new file mode 100644 (file)
index 0000000..f03f0a5
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2007, Intel Corporation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer. 
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the Intel Corporation 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 AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  Authors:  Steve Ayer, Adrian Burns
+ *            February, 2007
+ */
+/**
+ * @author Steve Ayer
+ * @author Adrian Burns
+ * @date February, 2007
+ *
+ * @author Mike Healy
+ * @date April 20, 2009 - ported to TinyOS 2.x 
+ */
+
+
+
+#include "RovingNetworks.h"
+
+interface Bluetooth {
+
+   /* write SPP (Serial Port Profile) data to the connected BT device */
+   command error_t write(const uint8_t *buf, uint16_t len);
+
+   /* after this command is called there will be no link to the connected device */
+   command error_t disconnect();
+
+   /* commands useful for Master(client) applications only */
+   /* do an BT Inquiry to discover all listening devices within range */
+   command void discoverDevices();
+
+   /* connect to a specific device that was previously discovered */
+   command error_t connect(uint8_t * addr);
+
+   // enum SLAVE_MODE, MASTER_MODE, TRIGGER_MASTER_MODE, AUTO_MASTER_MODE
+   command void setRadioMode(uint8_t mode);           
+
+   command void setDiscoverable(bool disc);
+   command void setEncryption(bool enc);
+   command void setAuthentication(bool auth);
+   command void setName(char * name);                  // max 16 chars
+   command void setPIN(char * name);                   // max 16 chars
+   command void setServiceClass(char * class);         // max 4 chars (hex word)
+   command void setServiceName(char * name);         // max 16 chars 
+   command void setDeviceClass(char * class);         // max 4 chars (hex word)
+   command void disableRemoteConfig(bool disableConfig);
+   command void setBaudrate(char * rate_factor);      // max 4 chars, must be integer
+   /* save power by minimising time Inquiry/Page scanning, call these commands from */
+   /* your StdControl.init() - module reset necessary for changes to take effect */
+   command void setPagingTime(char * hexval_time); // max 4 chars (hex word)
+   command void setInquiryTime(char * hexval_time); // max 4 chars (hex word)
+   command void resetDefaults();
+
+   /* whether or not it succeeded */
+   async event void connectionMade(uint8_t status);
+   async event void connectionClosed(uint8_t reason);
+   async event void commandModeEnded();
+   /*
+    * buffered data depends upon line demarcation or eot for this...
+    *     event void dataAvailable(uint8_t * data, uint16_t len);
+    * and this...
+    *    event void discoveryStatus(uint8_t * devices);
+    *
+    */
+   async event void dataAvailable(uint8_t data);
+   event void writeDone();
+}
+
+
diff --git a/tos/platforms/shimmer/chips/bluetooth/RovingNetworks.h b/tos/platforms/shimmer/chips/bluetooth/RovingNetworks.h
new file mode 100644 (file)
index 0000000..5a7d82d
--- /dev/null
@@ -0,0 +1,32 @@
+/* radioMode in enableBluetooth() can be set to one of the following modes,
+ see the RovingNetworks AT command set for further details on module configuration */
+
+#ifndef ROVINGNETWORKS_H
+#define ROVINGNETWORKS_H
+enum {
+  SLAVE_MODE,
+  MASTER_MODE,
+  TRIGGER_MASTER_MODE,
+  AUTO_MASTER_MODE    
+};
+
+enum { 
+  NADA,
+  INITIAL,
+  FINAL
+};
+/*
+const char * SETMODE =  "SM,";
+const char * SETMASTERMODE =  "SM,1";
+const char * SETSLAVEMODE =   "SM,0";
+const char * DISCOVERRADIOS = "I,";
+const char * DISCOVERRADIOS2 = ",0";
+
+const char * SETFASTBAUD    = "SU,115";
+const char * ENTERCOMMANDMODE = "$$$";
+const char * SETSLEEPMODE   = "SW,0300";
+const char * DIALRADIO      = "C,";
+const char * HANGUPRADIO    = "R,1";
+const char * WAKERADIO      = "";
+*/
+#endif
diff --git a/tos/platforms/shimmer/chips/bluetooth/RovingNetworksC.nc b/tos/platforms/shimmer/chips/bluetooth/RovingNetworksC.nc
new file mode 100644 (file)
index 0000000..046b12a
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, Intel Corporation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer. 
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the Intel Corporation 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 AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  Author:  Steve Ayer
+ *           February, 2007
+ */
+/**
+ * @author Steve Ayer
+ * @author Adrian Burns
+ * @date February, 2007
+ *
+ * @author Mike Healy
+ * @date April 20, 2009 - ported to TinyOS 2.x 
+ */
+
+
+
+configuration RovingNetworksC {
+   provides {
+      interface StdControl;
+      interface Bluetooth;
+      interface Init;
+   }
+}
+implementation {
+   components 
+     RovingNetworksP,
+     MainC,
+     HplMsp430InterruptC,  
+     HplMsp430Usart1C,     
+     LedsC;
+
+   StdControl = RovingNetworksP;
+   Bluetooth = RovingNetworksP;
+   Init = RovingNetworksP;
+
+   RovingNetworksP.UARTControl            -> HplMsp430Usart1C.HplMsp430Usart;
+   RovingNetworksP.UARTData               -> HplMsp430Usart1C.HplMsp430UsartInterrupts;
+   RovingNetworksP.RTSInterrupt           -> HplMsp430InterruptC.Port16;
+   RovingNetworksP.ConnectionInterrupt    -> HplMsp430InterruptC.Port15;
+   RovingNetworksP.Leds                   -> LedsC;
+
+}
diff --git a/tos/platforms/shimmer/chips/bluetooth/RovingNetworksP.nc b/tos/platforms/shimmer/chips/bluetooth/RovingNetworksP.nc
new file mode 100644 (file)
index 0000000..7f0b6b4
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2007, Intel Corporation
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, 
+ * this list of conditions and the following disclaimer. 
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the Intel Corporation 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 AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  Author:  Steve Ayer
+ *           February, 2007
+ */
+/**
+ * @author Steve Ayer
+ * @author Adrian Burns
+ * @date February, 2007
+ *
+ * @author Mike Healy
+ * @date April 20, 2009 - ported to TinyOS 2.x 
+ */
+
+
+#include "RovingNetworks.h"
+#include "Message.h"
+
+module RovingNetworksP {
+  provides {
+    interface Init;
+    interface StdControl;
+    interface Bluetooth;
+  }
+  uses {
+    interface HplMsp430Usart as UARTControl;
+    interface HplMsp430UsartInterrupts as UARTData;
+    interface HplMsp430Interrupt as RTSInterrupt;
+    interface HplMsp430Interrupt as ConnectionInterrupt;
+    interface Leds;
+  }
+}
+
+implementation {
+  extern int sprintf(char *str, const char *format, ...) __attribute__ ((C));
+  extern int snprintf(char *str, size_t len, const char *format, ...) __attribute__ ((C));
+
+  uint8_t radioMode, charsSent, setupStep;
+  bool discoverable, authenticate, encrypt, setNameRequest, setPINRequest, runDiscoveryRequest, resetDefaultsRequest,
+    setSvcClassRequest, setDevClassRequest, setSvcNameRequest, setCustomBaudrate, disableRemoteConfig, newMode,
+    setCustomInquiryTime, setCustomPagingTime;
+  norace bool transmissionOverflow, messageInProgress;
+  char expectedCommandResponse[8], newName[17], newPIN[17], newSvcClass[5], newDevClass[5], newSvcName[17], newBaudrate[5],
+    newInquiryTime[5], newPagingTime[5];
+  
+  norace struct Message outgoingMsg;
+  norace struct Message incomingMsg;
+   
+
+  task void sendNextChar() {
+    if(charsSent < outgoingMsg.length) {
+      call UARTControl.tx(msg_get_uint8(&outgoingMsg, charsSent));
+      atomic charsSent++;
+    } 
+    else{
+      messageInProgress = FALSE;
+      atomic if(!*expectedCommandResponse)
+       signal Bluetooth.writeDone();
+    }      
+  }
+  
+  command error_t Bluetooth.write(const uint8_t * buf, uint16_t len) { 
+    if(messageInProgress)
+      return FAIL;
+
+    messageInProgress = TRUE;
+    atomic charsSent = 0;
+    msg_clear(&outgoingMsg);
+    msg_append_buf(&outgoingMsg, buf, len);
+
+    if(!transmissionOverflow){
+      post sendNextChar();
+    }
+       
+    return SUCCESS;
+  }
+    
+  void initRN() {
+    register uint16_t i;
+    /*
+     * powerup state is reset == low (true); mike conrad of roving networks sez: 
+     * wait about 1/2 s after reset toggle
+     */
+    TOSH_SET_BT_RESET_PIN();    
+    for(i = 0; i< 400; i++)
+      TOSH_uwait(5000);
+
+    TOSH_MAKE_BT_PIO_INPUT();   // this is the connection interrupt pin, was default output
+    
+    call RTSInterrupt.edge(TRUE);  // initially, we look for a connection
+    call RTSInterrupt.enable();  // request to send raises when bt has trans overflow
+    call RTSInterrupt.clear();
+    
+    call ConnectionInterrupt.edge(TRUE);  // initially, we look for a connection
+    call ConnectionInterrupt.clear();
+    call ConnectionInterrupt.enable();  // interrupt upon connection state change (raises when connected, falls when dropped)
+
+    TOSH_CLR_BT_CTS_PIN();     // toggling cts wakes it up
+    TOSH_SET_BT_CTS_PIN();     
+    TOSH_uwait(5000);
+    TOSH_CLR_BT_CTS_PIN();     // tell bt module msp430 is ready
+  }
+
+  void setupUART() {
+    msp430_uart_union_config_t RN_uart_config = { {ubr: UBR_1MHZ_115200, umctl: UMCTL_1MHZ_115200, 
+                                                  ssel: 0x02, pena: 0, pev: 0, spb: 0, clen: 1,listen: 0, mm: 0, ckpl: 0, urxse: 0, urxeie: 0, 
+                                                  urxwie: 0, utxe : 1, urxe :1} };
+
+#ifdef USE_8MHZ_CRYSTAL           // we need exact divisors, else the thing acts unpredictably
+    call UARTControl.setUbr(0x08);
+    call UARTControl.setUmctl(0xee);
+#endif
+    call UARTControl.setModeUart(&RN_uart_config); // set to UART mode
+
+    call UARTControl.enableTxIntr();
+    call UARTControl.enableRxIntr();
+  }
+
+  void disableRN() {
+    TOSH_CLR_BT_RESET_PIN();
+    call UARTControl.disableUart();
+    call RTSInterrupt.disable();  
+    call ConnectionInterrupt.disable();  
+  }
+
+  error_t writeCommand(char * cmd, char * response) {
+    atomic strcpy(expectedCommandResponse, response);
+    if(call Bluetooth.write(cmd, strlen(cmd)) == FAIL)
+      return FAIL;
+
+    return SUCCESS;
+  }
+
+  command void Bluetooth.setRadioMode(uint8_t mode){
+    newMode = TRUE;
+    radioMode = mode;
+  }    
+
+  command void Bluetooth.setDiscoverable(bool disc){
+    discoverable = disc;  
+  }    
+
+  command void Bluetooth.setEncryption(bool enc){
+    encrypt = enc; 
+  }    
+
+  command void Bluetooth.setAuthentication(bool auth){
+    authenticate = auth;
+  }    
+
+  command void Bluetooth.disableRemoteConfig(bool disableConfig){
+    disableRemoteConfig = disableConfig;
+  }    
+
+  command void Bluetooth.resetDefaults(){
+    resetDefaultsRequest = TRUE;
+  }    
+
+  command void Bluetooth.setName(char * name){
+    setNameRequest = TRUE;
+    snprintf(newName, 17, "%s", name);
+  }    
+
+  command void Bluetooth.setDeviceClass(char * class){
+    setDevClassRequest = TRUE;
+    snprintf(newDevClass, 5, "%s", class);
+  }    
+
+  command void Bluetooth.setServiceClass(char * class){
+    setSvcClassRequest = TRUE;
+    snprintf(newSvcClass, 5, "%s", class);
+  }    
+
+  command void Bluetooth.setServiceName(char * name){
+    setSvcNameRequest = TRUE;
+    snprintf(newSvcName, 5, "%s", name);
+  }    
+
+  /* 
+   * this one makes sense only to roving networks
+   * the supplied "rate_factor" is the baudrate * 0.004096
+   * this factor must be an integer value...
+   */
+  command void Bluetooth.setBaudrate(char * rate_factor){
+    setCustomBaudrate = TRUE;
+    snprintf(newBaudrate, 5, "%s", rate_factor);
+  }    
+
+  command void Bluetooth.setPIN(char * PIN){
+    setPINRequest = TRUE;
+    snprintf(newPIN, 17, "%s", PIN);
+  }    
+
+  /* 
+   * Sets the Inquiry Scan Window - amount of time device 
+   * spends enabling inquiry scan (discoverability).
+   * Minimum = (hex word) "0012", corresponding to about 1% duty cycle.
+   * Maximum = (hex word) "1000"
+   */
+  command void Bluetooth.setInquiryTime(char * hexval_time){
+    setCustomInquiryTime = TRUE;
+    snprintf(newInquiryTime, 5, "%s", hexval_time);
+  }    
+
+  /* 
+   * Sets the Paging Scan Window - amount of time device 
+   * spends enabling page scan (connectability).
+   * Minimum = (hex word) "0012", corresponding to about 1% duty cycle.
+   * Maximum = (hex word) "1000"
+   */
+  command void Bluetooth.setPagingTime(char * hexval_time){
+    setCustomPagingTime = TRUE;
+    snprintf(newPagingTime, 5, "%s", hexval_time);
+  }    
+
+  /*
+   * this one is weird.  we need to do one at a time; the only way
+   * to get back is if the previous command responds properly and calls
+   * back to runSetCommands().  so if we get into command mode, each time here 
+   * we have to send another command.  we keep falling down the switch 
+   * until we find it, eventually hitting end.
+   */
+  task void runSetCommands() {
+    char commandbuf[32];
+
+    switch(setupStep) {
+    case 0:
+      setupStep++;
+      writeCommand("$$$", "CMD");
+      break;
+    case 1:
+      setupStep++;
+      // reset factory defaults
+      if(resetDefaultsRequest){
+       writeCommand("SF,1\r", "AOK");
+       break;
+      }
+    case 2:
+      setupStep++;
+      // default is slave (== 0), otherwise set mode
+      if(newMode){
+       sprintf(commandbuf, "SM,%d\r", radioMode);
+       writeCommand(commandbuf, "AOK");
+       break;
+      }
+    case 3:
+      setupStep++;
+      /*
+       * device is discoverable with a non-zero inquiry scan window
+       * default "time" is 0x0200 (units unspecified)
+       */
+      if(!discoverable){
+       writeCommand("SI,0000\r", "AOK");
+       break;
+      }
+    case 4:
+      setupStep++;
+      // device default is off
+      if(authenticate){
+       writeCommand("SA,1\r", "AOK");
+       break;
+      }
+    case 5:
+      setupStep++;
+      // device default is off
+      if(encrypt){
+       writeCommand("SE,1\r", "AOK");
+       break;
+      }
+    case 6:
+      setupStep++;
+      // default is none
+      if(setNameRequest){
+       sprintf(commandbuf, "SN,%s\r", newName);
+       writeCommand(commandbuf, "AOK");
+       break;
+      }
+    case 7:
+      setupStep++;
+      // default is none
+      if(setPINRequest){
+       sprintf(commandbuf, "SP,%s\r", newPIN);
+       writeCommand(commandbuf, "AOK");
+       break;
+      }
+    case 8:
+      setupStep++;
+      if(setSvcClassRequest){
+       sprintf(commandbuf, "SC,%s\r", newSvcClass);
+       writeCommand(commandbuf, "AOK");
+       break;
+      }
+    case 9:
+      setupStep++;
+      if(setDevClassRequest){
+       sprintf(commandbuf, "SD,%s\r", newDevClass);
+       writeCommand(commandbuf, "AOK");
+       break;
+      }
+    case 10:
+      setupStep++;
+      if(setSvcNameRequest){
+       sprintf(commandbuf, "SS,%s\r", newSvcName);
+       writeCommand(commandbuf, "AOK");
+       break;
+      }
+    case 11:
+      setupStep++;
+      if(setCustomBaudrate){
+       // set the baudrate to suit the MSP430 running at 8Mhz
+       sprintf(commandbuf, "SZ,%s\r", newBaudrate);
+       writeCommand(commandbuf, "AOK");
+       break;
+      }
+    case 12:
+      setupStep++;
+      if(disableRemoteConfig){
+       // disable remote configuration to enhance throughput
+       writeCommand("ST,0\r", "AOK");
+      }
+      else{
+       // disable remote configuration to enhance throughput
+       writeCommand("ST,60\r", "AOK");
+      }
+      break;
+    case 13:
+      setupStep++;
+      if(setCustomInquiryTime){
+       sprintf(commandbuf, "SI,%s\r", newInquiryTime);
+       writeCommand(commandbuf, "AOK");
+      }
+      else{
+       // to save power only leave inquiry on for approx 40msec (every 1.28 secs)
+       writeCommand("SI,0040\r", "AOK");
+      }
+      break;
+    case 14:
+      setupStep++;
+      if(setCustomPagingTime){
+       sprintf(commandbuf, "SJ,%s\r", newPagingTime);
+       writeCommand(commandbuf, "AOK");
+      }
+      else{
+       // to save power only leave paging on for approx 80msec (every 1.28 secs)
+       writeCommand("SJ,0080\r", "AOK");
+      }
+      break;
+    case 15:
+      setupStep++;
+      // exit command mode
+      writeCommand("---\r", "END");
+      break;
+    default:
+      break;
+    }
+  }  
+
+  command error_t Init.init(){
+    TOSH_MAKE_BT_RTS_INPUT();      
+    
+    TOSH_MAKE_BT_RXD_INPUT();
+    TOSH_SEL_BT_RXD_MODFUNC();
+    
+    // this powers it up on models so equipped, otherwise harmless 
+#ifdef BT_PWR_LOGIC_TRUE
+    TOSH_SET_SW_BT_PWR_N_PIN();
+#else  
+    TOSH_CLR_SW_BT_PWR_N_PIN();   
+#endif
+    
+    newMode = FALSE;
+    radioMode = SLAVE_MODE;   
+    discoverable = TRUE;
+    authenticate = FALSE;
+    encrypt = FALSE;
+    resetDefaultsRequest = FALSE;
+    setNameRequest = FALSE;
+    setPINRequest = FALSE;
+    setSvcClassRequest = FALSE;
+    setSvcNameRequest = FALSE;
+    setDevClassRequest = FALSE;
+    setCustomBaudrate = FALSE;
+    disableRemoteConfig = FALSE;
+    setCustomInquiryTime = FALSE;
+    setCustomPagingTime = FALSE;
+    
+    setupStep = 0;
+    atomic *expectedCommandResponse = 0;   // NULL pointer
+    transmissionOverflow = FALSE, messageInProgress = FALSE;
+
+    initRN();
+    setupUART();
+
+    return SUCCESS;
+  }
+
+  command error_t StdControl.start(){
+    TOSH_uwait(15000);
+    post runSetCommands();
+
+    return SUCCESS;
+  }
+
+  command error_t StdControl.stop(){
+    disableRN();
+    
+#ifdef BT_PWR_LOGIC_TRUE
+    TOSH_CLR_SW_BT_PWR_N_PIN();
+#else  
+    TOSH_SET_SW_BT_PWR_N_PIN();   
+#endif
+    
+    return SUCCESS;
+  }
+  
+  /* after this command is called there will be no link to the connected device */
+  command error_t Bluetooth.disconnect(){
+    call Bluetooth.write("K,\r", 3);
+  }
+
+  /* commands useful for Master(client) applications only */
+  /* do an BT Inquiry to discover all listening devices within range */
+  command void Bluetooth.discoverDevices() {
+    if(!radioMode)     // we're a slave, shouldn't do this
+      return;
+
+    runDiscoveryRequest = TRUE;
+  }    
+
+  /* connect to a specific device that was previously discovered */
+  command error_t Bluetooth.connect(uint8_t * addr) {
+    char buffer[64];
+
+    sprintf(buffer, "C,%s\r", addr);
+    return writeCommand(buffer, "AOK");
+  }
+     
+  async event void UARTData.rxDone(uint8_t data) {        
+    if(!*expectedCommandResponse){
+      signal Bluetooth.dataAvailable(data);
+    }
+    else{
+      if(isalpha(data)){
+       msg_append_uint8(&incomingMsg, data);
+       if(msg_cmp_buf(&incomingMsg,            // which is affirmative
+                      0, 
+                      expectedCommandResponse,
+                      strlen(expectedCommandResponse))){
+         msg_clear(&incomingMsg);      
+         if(!strcmp(expectedCommandResponse, "END"))
+           signal Bluetooth.commandModeEnded();  //call Leds.greenOn();
+         else
+           post runSetCommands();
+         atomic *expectedCommandResponse = '\0';
+       }
+      }
+      else
+       msg_clear(&incomingMsg);
+    }
+  }
+
+  async event void UARTData.txDone() {
+    if (!transmissionOverflow) {
+      post sendNextChar();
+    }
+  }
+    
+  // Interrupt associated with radio flow control.  Ensures that there are no buffer overflows.
+  async event void RTSInterrupt.fired() {
+    if (call RTSInterrupt.getValue() == TRUE) {
+      transmissionOverflow = 1;
+      call RTSInterrupt.edge(FALSE);
+    } 
+    else{
+      atomic transmissionOverflow = 0;
+      post sendNextChar();
+      call RTSInterrupt.edge(TRUE);
+    }
+    atomic call RTSInterrupt.clear();
+  }
+  
+  async event void ConnectionInterrupt.fired() {
+    if(call ConnectionInterrupt.getValue() == TRUE){
+      call ConnectionInterrupt.edge(FALSE);
+      signal Bluetooth.connectionMade(SUCCESS);
+    }
+    else{
+      call ConnectionInterrupt.edge(TRUE);
+      signal Bluetooth.connectionClosed(0);
+    }
+    atomic call ConnectionInterrupt.clear();
+  }
+}