Beispiel #1
0
/*JSON{ "type":"method", "class": "Serial", "name" : "setup",
         "description" : ["Setup this Serial port with the given baud rate and options.",
                          "If not specified in options, the default pins are used (usually the lowest numbered pins on the lowest port that supports this peripheral)"],
         "generate" : "jswrap_serial_setup",
         "params" : [ [ "baudrate", "JsVar", "The baud rate - the default is 9600"],
                      [ "options", "JsVar", ["An optional structure containing extra information on initialising the serial port.",
                                             "```{rx:pin,tx:pin,bytesize:8,parity:null/'none'/'o'/'odd'/'e'/'even',stopbits:1}```",
                                             "You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `UART`/`USART` markers.",
                                             "Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite" ] ] ]
}*/
void jswrap_serial_setup(JsVar *parent, JsVar *baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_USART(device)) return;

  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (!jsvIsUndefined(baud)) {
    int b = (int)jsvGetInteger(baud);
    if (b<=100 || b > 10000000)
      jsExceptionHere(JSET_ERROR, "Invalid baud rate specified");
    else
      inf.baudRate = b;
  }


  if (jsvIsObject(options)) {
    inf.pinRX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "rx", 0));
    inf.pinTX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "tx", 0));    

    JsVar *v;
    v = jsvObjectGetChild(options, "bytesize", 0);
    if (jsvIsInt(v)) 
      inf.bytesize = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
    
    inf.parity = 0;
    v = jsvObjectGetChild(options, "parity", 0);
    if(jsvIsString(v)) {
      if(jsvIsStringEqual(v, "o") || jsvIsStringEqual(v, "odd"))
        inf.parity = 1;
      else if(jsvIsStringEqual(v, "e") || jsvIsStringEqual(v, "even"))
        inf.parity = 2;
    } else if(jsvIsInt(v)) {
      inf.parity = (unsigned char)jsvGetInteger(v);
    }
    jsvUnLock(v);
    if (inf.parity>2) {
      jsExceptionHere(JSET_ERROR, "Invalid parity %d", inf.parity);
      return;
    }

    v = jsvObjectGetChild(options, "stopbits", 0);
    if (jsvIsInt(v)) 
      inf.stopbits = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  if (inf.baudRate != DEFAULT_BAUD_RATE) {
    jsvUnLock(jsvObjectSetChild(parent, USART_BAUDRATE_NAME, jsvNewFromInteger(inf.baudRate)));
  } else
    jsvRemoveNamedChild(parent, USART_BAUDRATE_NAME);
  // Do the same for options
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
/*JSON{ "type":"method", "class": "Serial", "name" : "setup",
         "description" : "Setup this Serial port with the given baud rate and options",
         "generate" : "jswrap_serial_setup",
         "params" : [ [ "baudrate", "int", "The baud rate - the default is 9600"],
                      [ "options", "JsVar", ["An optional structure containing extra information on initialising the serial port.",
                                             "```{rx:pin,tx:pin}```",
                                             "Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite" ] ] ]
}*/
void jswrap_serial_setup(JsVar *parent, JsVarInt baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (baud>0) inf.baudRate = (int)baud;

  if (jsvIsObject(options)) {

    inf.pinRX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "rx", 0));
    inf.pinTX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "tx", 0));
    inf.bytesize = (unsigned char)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "bytesize", 0));

    JsVar *v;
    v = jsvObjectGetChild(options, "parity", 0);
    
    if(jsvIsNull(v)) {
      inf.parity = 0;
    }
    else if(jsvIsString(v)) {
      inf.parity = 0xFF;
      char s[8] = "";

      jsvGetString(v, s, sizeof(s) - 1);

      if(!strcmp(s, "o") || !strcmp(s, "odd")) {
        inf.parity = 1;
      }
      else if(!strcmp(s, "e") || !strcmp(s, "even")) {
        inf.parity = 2;
      }
    }
    else if(jsvIsInt(v)) {
      inf.parity = (unsigned char)jsvGetInteger(v);
    }

    jsvUnLock(v);

    v = jsvObjectGetChild(options, "stopbits", 0);
    inf.stopbits = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  if (baud != DEFAULT_BAUD_RATE) {
    JsVar *baudVar = jsvNewFromInteger(baud);
    jsvUnLock(jsvSetNamedChild(parent, baudVar, USART_BAUDRATE_NAME));
    jsvUnLock(baudVar);
  } else
    jsvRemoveNamedChild(parent, USART_BAUDRATE_NAME);
  // Do the same for options
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Beispiel #3
0
/** Push data into a stream. To be used by Espruino (not a user).
 * This either calls the on('data') handler if it exists, or it
 * puts the data in a buffer. This MAY CLAIM the string that is
 * passed in.
 *
 * This will return true on success, or false if the buffer is
 * full. Setting force=true will attempt to fill the buffer as
 * full as possible, and will raise an error flag if data is lost.
 */
bool jswrap_stream_pushData(JsVar *parent, JsVar *dataString, bool force) {
  assert(jsvIsObject(parent));
  assert(jsvIsString(dataString));
  bool ok = true;

  JsVar *callback = jsvFindChildFromString(parent, STREAM_CALLBACK_NAME, false);
  if (callback) {
    if (!jsiExecuteEventCallback(parent, callback, dataString, 0)) {
      jsError("Error processing Serial data handler - removing it.");
      jsErrorFlags |= JSERR_CALLBACK;
      jsvRemoveNamedChild(parent, STREAM_CALLBACK_NAME);
    }
    jsvUnLock(callback);
  } else {
    // No callback - try and add buffer
    JsVar *buf = jsvObjectGetChild(parent, STREAM_BUFFER_NAME, 0);
    if (!jsvIsString(buf)) {
      // no buffer, just set this one up
      jsvObjectSetChild(parent, STREAM_BUFFER_NAME, dataString);
    } else {
      // append (if there is room!)
      size_t bufLen = jsvGetStringLength(buf);
      size_t dataLen = jsvGetStringLength(dataString);
      if (bufLen + dataLen > STREAM_MAX_BUFFER_SIZE) {
        if (force) jsErrorFlags |= JSERR_BUFFER_FULL;
        // jsWarn("String buffer overflowed maximum size (%d)", STREAM_MAX_BUFFER_SIZE);
        ok = false;
      }
      if ((ok || force) && (bufLen < STREAM_MAX_BUFFER_SIZE))
        jsvAppendStringVar(buf, dataString, 0, STREAM_MAX_BUFFER_SIZE-bufLen);
      jsvUnLock(buf);
    }
  }
  return ok;
}
Beispiel #4
0
/*JSON{
  "type" : "method",
  "class" : "SPI",
  "name" : "setup",
  "generate" : "jswrap_spi_setup",
  "params" : [
    ["options","JsVar",["An optional structure containing extra information on initialising the SPI port","Please note that baud rate is set to the nearest that can be managed - which may be -+ 50%","```{sck:pin, miso:pin, mosi:pin, baud:integer=100000, mode:integer=0, order:'msb'/'lsb'='msb' }```","If sck,miso and mosi are left out, they will automatically be chosen. However if one or more is specified then the unspecified pins will not be set up.","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `SPI` marker.","The SPI ```mode``` is between 0 and 3 - see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Clock_polarity_and_phase","On STM32F1-based parts, you cannot mix AF and non-AF pins (SPI pins are usually grouped on the chip - and you can't mix pins from two groups). Espruino will not warn you about this."]]
  ]
}
Set up this SPI port as an SPI Master.
*/
void jswrap_spi_setup(JsVar *parent, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  JshSPIInfo inf;
  jsspiPopulateSPIInfo(&inf, options);

  if (DEVICE_IS_SPI(device)) {
    jshSPISetup(device, &inf);
#ifdef LINUX
    if (jsvIsObject(options)) {
      jsvUnLock(jsvObjectSetChild(parent, "path", jsvObjectGetChild(options, "path", 0)));
    }
#endif
  } else if (device == EV_NONE) {
    // software mode - at least configure pins properly
    if (inf.pinSCK != PIN_UNDEFINED)
      jshPinSetState(inf.pinSCK,  JSHPINSTATE_GPIO_OUT);
    if (inf.pinMISO != PIN_UNDEFINED)
      jshPinSetState(inf.pinMISO,  JSHPINSTATE_GPIO_IN);
    if (inf.pinMOSI != PIN_UNDEFINED)
      jshPinSetState(inf.pinMOSI,  JSHPINSTATE_GPIO_OUT);
  } else return;
  // Set up options, so we can initialise it on startup
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Beispiel #5
0
/*JSON{
  "type" : "method",
  "class" : "Object",
  "name" : "on",
  "generate" : "jswrap_object_on",
  "params" : [
    ["event","JsVar","The name of the event, for instance 'data'"],
    ["listener","JsVar","The listener to call when this event is received"]
  ]
}
Register an event listener for this object, for instance ```http.on('data', function(d) {...})```. See Node.js's EventEmitter.
 */
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
  if (!jsvHasChildren(parent)) {
    jsWarn("Parent must be an object - not a String, Integer, etc.");
    return;
  }
  if (!jsvIsString(event)) {
    jsWarn("First argument to EventEmitter.on(..) must be a string");
    return;
  }
  if (!jsvIsFunction(listener) && !jsvIsString(listener)) {
    jsWarn("Second argument to EventEmitter.on(..) must be a function or a String (containing code)");
    return;
  }

  JsVar *eventName = jsvVarPrintf(JS_EVENT_PREFIX"%s",event);
  if (!eventName) return; // no memory

  JsVar *eventList = jsvFindChildFromVar(parent, eventName, true);
  jsvUnLock(eventName);
  JsVar *eventListeners = jsvSkipName(eventList);
  if (jsvIsUndefined(eventListeners)) {
    // just add
    jsvSetValueOfName(eventList, listener);
  } else {
    if (jsvIsArray(eventListeners)) {
      // we already have an array, just add to it
      jsvArrayPush(eventListeners, listener);
    } else {
      // not an array - we need to make it an array
      JsVar *arr = jsvNewEmptyArray();
      jsvArrayPush(arr, eventListeners);
      jsvArrayPush(arr, listener);
      jsvSetValueOfName(eventList, arr);
      jsvUnLock(arr);
    }
  }
  jsvUnLock2(eventListeners, eventList);
  /* Special case if we're a data listener and data has already arrived then
   * we queue an event immediately. */
  if (jsvIsStringEqual(event, "data")) {
    JsVar *buf = jsvObjectGetChild(parent, STREAM_BUFFER_NAME, 0);
    if (jsvIsString(buf)) {
      jsiQueueObjectCallbacks(parent, STREAM_CALLBACK_NAME, &buf, 1);
      jsvRemoveNamedChild(parent, STREAM_BUFFER_NAME);
    }
    jsvUnLock(buf);
  }
}
Beispiel #6
0
/*JSON{
  "type" : "method",
  "class" : "Object",
  "name" : "on",
  "generate" : "jswrap_object_on",
  "params" : [
    ["event","JsVar","The name of the event, for instance 'data'"],
    ["listener","JsVar","The listener to call when this event is received"]
  ]
}
Register an event listener for this object, for instance ```http.on('data', function(d) {...})```. See Node.js's EventEmitter.
*/
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
  if (!jsvIsObject(parent)) {
      jsWarn("Parent must be a proper object - not a String, Integer, etc.");
      return;
    }
  if (!jsvIsString(event)) {
      jsWarn("First argument to EventEmitter.on(..) must be a string");
      return;
    }
  if (!jsvIsFunction(listener) && !jsvIsString(listener)) {
    jsWarn("Second argument to EventEmitter.on(..) must be a function or a String (containing code)");
    return;
  }
  char eventName[16] = "#on";
  jsvGetString(event, &eventName[3], sizeof(eventName)-4);

  JsVar *eventList = jsvFindChildFromString(parent, eventName, true);
  JsVar *eventListeners = jsvSkipName(eventList);
  if (jsvIsUndefined(eventListeners)) {
    // just add
    jsvSetValueOfName(eventList, listener);
  } else {
    if (jsvIsArray(eventListeners)) {
      // we already have an array, just add to it
      jsvArrayPush(eventListeners, listener);
    } else {
      // not an array - we need to make it an array
      JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
      jsvArrayPush(arr, eventListeners);
      jsvArrayPush(arr, listener);
      jsvSetValueOfName(eventList, arr);
      jsvUnLock(arr);
    }
  }
  jsvUnLock(eventListeners);
  jsvUnLock(eventList);
  /* Special case if we're a data listener and data has already arrived then
   * we queue an event immediately. */
  if (jsvIsStringEqual(event, "data")) {
    JsVar *buf = jsvObjectGetChild(parent, STREAM_BUFFER_NAME, 0);
    if (jsvIsString(buf)) {
      jsiQueueObjectCallbacks(parent, "#ondata", &buf, 1);
      jsvRemoveNamedChild(parent, STREAM_BUFFER_NAME);
    }
    jsvUnLock(buf);
  }
}
Beispiel #7
0
/*JSON{
  "type" : "method",
  "class" : "I2C",
  "name" : "setup",
  "generate" : "jswrap_i2c_setup",
  "params" : [
    ["options","JsVar",["An optional structure containing extra information on initialising the I2C port","```{scl:pin, sda:pin, bitrate:100000}```","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `I2C` marker. Note that 400000kHz is the maximum bitrate for most parts."]]
  ]
}
Set up this I2C port

If not specified in options, the default pins are used (usually the lowest numbered pins on the lowest port that supports this peripheral)
 */
void jswrap_i2c_setup(JsVar *parent, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_I2C(device)) return;
  JshI2CInfo inf;
  jshI2CInitInfo(&inf);
  if (jsvIsObject(options)) {
    inf.pinSCL = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "scl", 0));
    inf.pinSDA = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "sda", 0));
    JsVar *v = jsvObjectGetChild(options, "bitrate", 0);
    if (v)
      inf.bitrate = jsvGetIntegerAndUnLock(v);
  }
  jshI2CSetup(device, &inf);
  // Set up options, so we can initialise it on startup
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Beispiel #8
0
/*JSON{
  "type" : "method",
  "class" : "SPI",
  "name" : "setup",
  "generate" : "jswrap_spi_setup",
  "params" : [
    ["options","JsVar",["An optional structure containing extra information on initialising the SPI port","Please note that baud rate is set to the nearest that can be managed - which may be -+ 50%","```{sck:pin, miso:pin, mosi:pin, baud:integer=100000, mode:integer=0, order:'msb'/'lsb'='msb' }```","If sck,miso and mosi are left out, they will automatically be chosen. However if one or more is specified then the unspecified pins will not be set up.","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `SPI` marker.","The SPI ```mode``` is between 0 and 3 - see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Clock_polarity_and_phase","On STM32F1-based parts, you cannot mix AF and non-AF pins (SPI pins are usually grouped on the chip - and you can't mix pins from two groups). Espruino will not warn you about this."]]
  ]
}
Set up this SPI port as an SPI Master.
 */
void jswrap_spi_setup(
    JsVar *parent, //!< The variable that is the class instance of this function.
    JsVar *options //!< The options controlling SPI.
  ) {
  //
  // Design: The options variable is a JS Object which contains a series of settings.  These
  // settings are parsed by `jsspiPopulateSPIInfo` to populate a C structure of type
  // `JshSPIInfo`.
  //
  // The options are also hung off the class instance variable in a property symbolically called
  // DEVICE_OPTIONS_NAME ("_options").
  //
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  JshSPIInfo inf;

  // Debug
  // jsiConsolePrintf("jswrap_spi_setup called parent=%v, options=%v\n", parent, options);

  jsspiPopulateSPIInfo(&inf, options);

  if (DEVICE_IS_SPI(device)) {
    jshSPISetup(device, &inf);
#ifdef LINUX
    if (jsvIsObject(options)) {
      jsvObjectSetChildAndUnLock(parent, "path", jsvObjectGetChild(options, "path", 0));
    }
#endif
  } else if (device == EV_NONE) {
    // software mode - at least configure pins properly
    if (inf.pinSCK != PIN_UNDEFINED)
      jshPinSetState(inf.pinSCK,  JSHPINSTATE_GPIO_OUT);
    if (inf.pinMISO != PIN_UNDEFINED)
      jshPinSetState(inf.pinMISO,  JSHPINSTATE_GPIO_IN);
    if (inf.pinMOSI != PIN_UNDEFINED)
      jshPinSetState(inf.pinMOSI,  JSHPINSTATE_GPIO_OUT);
  } else return;
  // Set up options, so we can initialise it on startup
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Beispiel #9
0
// Return a string containing 'chars' bytes. If chars<=0 the string will be all available data
JsVar *jswrap_stream_read(JsVar *parent, JsVarInt chars) {
  if (!jsvIsObject(parent)) return 0;
  JsVar *buf = jsvObjectGetChild(parent, STREAM_BUFFER_NAME, 0);
  JsVar *data = 0;
  if (jsvIsString(buf)) {
    size_t len = jsvGetStringLength(buf);
    if (chars <= 0 || (size_t)chars>=len) {
      // return the whole buffer and remove it
      data = buf;
      buf = 0;
      jsvRemoveNamedChild(parent, STREAM_BUFFER_NAME);
    } else {
      // return just part of the buffer, and shorten it accordingly
      data = jsvNewFromStringVar(buf, 0, (size_t)chars);
      JsVar *newBuf = jsvNewFromStringVar(buf, (size_t)chars, JSVAPPENDSTRINGVAR_MAXLENGTH);
      jsvUnLock(jsvObjectSetChild(parent, STREAM_BUFFER_NAME, newBuf));
    }
  } else
    data = jsvNewFromEmptyString();
  jsvUnLock(buf);
  return data;
}
Beispiel #10
0
/*JSON{
  "type" : "method",
  "class" : "Serial",
  "name" : "setup",
  "generate" : "jswrap_serial_setup",
  "params" : [
    ["baudrate","JsVar","The baud rate - the default is 9600"],
    ["options","JsVar",["An optional structure containing extra information on initialising the serial port.","```{rx:pin,tx:pin,bytesize:8,parity:null/'none'/'o'/'odd'/'e'/'even',stopbits:1,flow:null/undefined/'none'/'xon'}```","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `UART`/`USART` markers.","Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite"]]
  ]
}
Setup this Serial port with the given baud rate and options.

If not specified in options, the default pins are used (usually the lowest numbered pins on the lowest port that supports this peripheral)
 */
void jswrap_serial_setup(JsVar *parent, JsVar *baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_USART(device)) return;

  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (jsvIsUndefined(options)) {
    options = jsvObjectGetChild(parent, DEVICE_OPTIONS_NAME, 0);
  } else
    jsvLockAgain(options);

  JsVar *parity = 0;
  JsVar *flow = 0;
  jsvConfigObject configs[] = {
      {"rx", JSV_PIN, &inf.pinRX},
      {"tx", JSV_PIN, &inf.pinTX},
      {"ck", JSV_PIN, &inf.pinCK},
      {"bytesize", JSV_INTEGER, &inf.bytesize},
      {"stopbits", JSV_INTEGER, &inf.stopbits},
      {"parity", JSV_OBJECT /* a variable */, &parity},
      {"flow", JSV_OBJECT /* a variable */, &flow},
  };



  if (!jsvIsUndefined(baud)) {
    int b = (int)jsvGetInteger(baud);
    if (b<=100 || b > 10000000)
      jsExceptionHere(JSET_ERROR, "Invalid baud rate specified");
    else
      inf.baudRate = b;
  }

  bool ok = true;
  if (jsvReadConfigObject(options, configs, sizeof(configs) / sizeof(jsvConfigObject))) {
    // sort out parity
    inf.parity = 0;
    if(jsvIsString(parity)) {
      if (jsvIsStringEqual(parity, "o") || jsvIsStringEqual(parity, "odd"))
        inf.parity = 1;
      else if (jsvIsStringEqual(parity, "e") || jsvIsStringEqual(parity, "even"))
        inf.parity = 2;
    } else if (jsvIsInt(parity)) {
      inf.parity = (unsigned char)jsvGetInteger(parity);
    }
    if (inf.parity>2) {
      jsExceptionHere(JSET_ERROR, "Invalid parity %d", inf.parity);
      ok = false;
    }

    if (ok) {
      if (jsvIsUndefined(flow) || jsvIsNull(flow) || jsvIsStringEqual(flow, "none"))
        inf.xOnXOff = false;
      else if (jsvIsStringEqual(flow, "xon"))
        inf.xOnXOff = true;
      else {
        jsExceptionHere(JSET_ERROR, "Invalid flow control: %q", flow);
        ok = false;
      }
    }

#ifdef LINUX
    if (ok && jsvIsObject(options))
      jsvObjectSetChildAndUnLock(parent, "path", jsvObjectGetChild(options, "path", 0));
#endif
  }
  jsvUnLock(parity);
  jsvUnLock(flow);
  if (!ok) {
    jsvUnLock(options);
    return;
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  jsvObjectSetChildAndUnLock(parent, USART_BAUDRATE_NAME, jsvNewFromInteger(inf.baudRate));
  // Do the same for options
  if (options)
    jsvObjectSetChildAndUnLock(parent, DEVICE_OPTIONS_NAME, options);
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}