diff --git a/carbon/hal/atmegau2.c b/carbon/hal/atmegau2.c index cb93da21f..d08a898d5 100644 --- a/carbon/hal/atmegau2.c +++ b/carbon/hal/atmegau2.c @@ -7,17 +7,17 @@ int carbon_select_u2_gpio(struct _lf_device *device) { struct _carbon_context *context = device->_ctx; lf_assert(context, failure, E_NULL, "No context for selected carbon device."); struct _lf_device *u2 = context->_u2; - LF_MODULE_SET_DEVICE_AND_ID(_gpio, u2, _gpio_id); + _gpio.index = _gpio_id; return lf_success; failure: return lf_error; } int carbon_select_atmegau2(struct _lf_device *device) { - LF_MODULE_SET_DEVICE_AND_ID(_button, device, _button_id); -// LF_MODULE_SET_DEVICE_AND_ID(_gpio, device, _gpio_id); - LF_MODULE_SET_DEVICE_AND_ID(_led, device, _led_id); - LF_MODULE_SET_DEVICE_AND_ID(_uart0, device, _uart0_id); - LF_MODULE_SET_DEVICE_AND_ID(_wdt, device, _wdt_id); + _button.index = _button_id;; +// _gpio.index = _gpio_id;; + _led.index = _led_id;; + _uart0.index = _uart0_id;; + _wdt.index = _wdt_id;; return lf_success; } diff --git a/carbon/hal/atsam4s.c b/carbon/hal/atsam4s.c index 5ba44542e..8fb7d2099 100644 --- a/carbon/hal/atsam4s.c +++ b/carbon/hal/atsam4s.c @@ -4,23 +4,23 @@ #include int carbon_select_atsam4s(struct _lf_device *device) { - LF_MODULE_SET_DEVICE_AND_ID(_adc, device, _adc_id); - LF_MODULE_SET_DEVICE_AND_ID(_button, device, _button_id); - LF_MODULE_SET_DEVICE_AND_ID(_dac, device, _dac_id); - LF_MODULE_SET_DEVICE_AND_ID(_fld, device, _fld_id); - LF_MODULE_SET_DEVICE_AND_ID(_gpio, device, _gpio_id); - LF_MODULE_SET_DEVICE_AND_ID(_i2c, device, _i2c_id); - LF_MODULE_SET_DEVICE_AND_ID(_led, device, _led_id); - LF_MODULE_SET_DEVICE_AND_ID(_pwm, device, _pwm_id); - LF_MODULE_SET_DEVICE_AND_ID(_rtc, device, _rtc_id); - LF_MODULE_SET_DEVICE_AND_ID(_spi, device, _spi_id); - LF_MODULE_SET_DEVICE_AND_ID(_swd, device, _swd_id); - LF_MODULE_SET_DEVICE_AND_ID(_task, device, _task_id); - LF_MODULE_SET_DEVICE_AND_ID(_temp, device, _temp_id); - LF_MODULE_SET_DEVICE_AND_ID(_timer, device, _timer_id); - LF_MODULE_SET_DEVICE_AND_ID(_uart0, device, _uart0_id); - LF_MODULE_SET_DEVICE_AND_ID(_usart, device, _usart_id); - LF_MODULE_SET_DEVICE_AND_ID(_usb, device, _usb_id); - LF_MODULE_SET_DEVICE_AND_ID(_wdt, device, _wdt_id); + _adc.index = _adc_id; + _button.index = _button_id; + _dac.index = _dac_id; + _fld.index = _fld_id; + _gpio.index = _gpio_id; + _i2c.index = _i2c_id; + _led.index = _led_id; + _pwm.index = _pwm_id; + _rtc.index = _rtc_id; + _spi.index = _spi_id; + _swd.index = _swd_id; + _task.index = _task_id; + _temp.index = _temp_id; + _timer.index = _timer_id; + _uart0.index = _uart0_id; + _usart.index = _usart_id; + _usb.index = _usb_id; + _wdt.index = _wdt_id; return lf_success; } diff --git a/console/src/bin/modules_cli.rs b/console/src/bin/modules_cli.rs index b9944bff3..e6cde2b84 100644 --- a/console/src/bin/modules_cli.rs +++ b/console/src/bin/modules_cli.rs @@ -117,7 +117,7 @@ pub mod led { let blue = args.value_of("blue").unwrap().parse::().unwrap(); let flipper = flipper::Flipper::attach(); - let led = flipper::fsm::led::Led::bind(&flipper); + let led = flipper::fsm::led::Led::new(&flipper); led.rgb(red, green, blue); Ok(()) } diff --git a/console/src/bindings/generators/templates/c.hbs b/console/src/bindings/generators/templates/c.hbs index aa9f87de8..a31cf1318 100644 --- a/console/src/bindings/generators/templates/c.hbs +++ b/console/src/bindings/generators/templates/c.hbs @@ -7,6 +7,6 @@ const struct _{{name}}_interface {{name}} { }; {{#each funcs}} LF_WEAK {{ret}} {{../name}}_{{name}}({{param_expansion params}}) { - {{ret}} result = lf_invoke(&_{{../name}}, _{{../name}}_{{name}}, {{ret_fmr}}, lf_args({{fmr_expansion params}})); + {{ret}} result = lf_invoke(lf_get_current_device(), &_{{../name}}, _{{../name}}_{{name}}, {{ret_fmr}}, lf_args({{fmr_expansion params}})); } {{/each}} \ No newline at end of file diff --git a/console/src/bindings/test_resources/dwarf_parse_test_macho_expected.c b/console/src/bindings/test_resources/dwarf_parse_test_macho_expected.c index bc4bd83ac..3fae8e5ef 100644 --- a/console/src/bindings/test_resources/dwarf_parse_test_macho_expected.c +++ b/console/src/bindings/test_resources/dwarf_parse_test_macho_expected.c @@ -7,5 +7,5 @@ const struct _user_interface user { }; LF_WEAK int user_test(int a, char b, long int c) { - int result = lf_invoke(&_user, _user_test, lf_uint32_t, lf_args(lf_infer(a), lf_infer(b), lf_infer(c))); + int result = lf_invoke(lf_get_current_device(), &_user, _user_test, lf_uint32_t, lf_args(lf_infer(a), lf_infer(b), lf_infer(c))); } diff --git a/console/src/bindings/test_resources/module_binding_test_expected.c b/console/src/bindings/test_resources/module_binding_test_expected.c index b82943414..aabb4283c 100644 --- a/console/src/bindings/test_resources/module_binding_test_expected.c +++ b/console/src/bindings/test_resources/module_binding_test_expected.c @@ -9,13 +9,13 @@ const struct _user_interface user { }; LF_WEAK char* user_test_four(uint8_t first, uint16_t second, uint32_t third) { - char* result = lf_invoke(&_user, _user_test_four, lf_uint8_t, lf_args(lf_infer(first), lf_infer(second), lf_infer(third))); + char* result = lf_invoke(lf_get_current_device(), &_user, _user_test_four, lf_uint8_t, lf_args(lf_infer(first), lf_infer(second), lf_infer(third))); } LF_WEAK int user_test_three(char letter) { - int result = lf_invoke(&_user, _user_test_three, lf_uint32_t, lf_args(lf_infer(letter))); + int result = lf_invoke(lf_get_current_device(), &_user, _user_test_three, lf_uint32_t, lf_args(lf_infer(letter))); } LF_WEAK void user_test_one() { - void result = lf_invoke(&_user, _user_test_one, lf_void_t, lf_args()); + void result = lf_invoke(lf_get_current_device(), &_user, _user_test_one, lf_void_t, lf_args()); } diff --git a/languages/java/src/main/java/io/flipper/Flipper.java b/languages/java/src/main/java/io/flipper/Flipper.java index 003436f0c..de143eb5a 100644 --- a/languages/java/src/main/java/io/flipper/Flipper.java +++ b/languages/java/src/main/java/io/flipper/Flipper.java @@ -21,7 +21,7 @@ public interface _libflipper { Pointer flipper_attach(); // FMR bindings - int lf_invoke(_lf_module module, byte function, Pointer parameters); + int lf_invoke(lf_get_current_device(), _lf_module module, byte function, Pointer parameters); int lf_bind(Pointer module); Pointer fmr_build(byte argc); @@ -55,7 +55,7 @@ public T bindModule(Class moduleInterface, String name) { * Upon receiving an invoke call, the ModuleInvocationHandler constructs a _fmr_list parameter list from the * function call and uses this FMRInvoker to deliver it back to us, where we can pass it to lf_invoke. */ - ModuleInvocationHandler invoker = new ModuleInvocationHandler(moduleInterface, (func, params) -> libflipper.lf_invoke(module, func, params)); + ModuleInvocationHandler invoker = new ModuleInvocationHandler(moduleInterface, (func, params) -> libflipper.lf_invoke(lf_get_current_device(), module, func, params)); return moduleInterface.cast(Proxy.newProxyInstance(moduleInterface.getClassLoader(), new Class[] { moduleInterface }, invoker)); } diff --git a/languages/js/.gitignore b/languages/js/.gitignore index c2669b881..6b57aaaf7 100644 --- a/languages/js/.gitignore +++ b/languages/js/.gitignore @@ -1,3 +1,4 @@ node_modules/ .idea/ *.iml +yarn.lock diff --git a/languages/js/flipper.js b/languages/js/flipper.js new file mode 100644 index 000000000..7f8581247 --- /dev/null +++ b/languages/js/flipper.js @@ -0,0 +1,151 @@ +const ffi = require('ffi'); +const ref = require('ref'); +const Struct = require('ref-struct'); + +// typedefs +const lf_version_t = ref.types.uint16; +const lf_crc_t = ref.types.uint16; + +const lf_value = ref.types.uint32; +const lf_function = ref.types.uint8; +const lf_return_t = ref.types.uint32; + +const _lf_type = [ + ref.types.uint8, + ref.types.uint16, + ref.types.void, + ref.types.uint32, +]; + +const lf_type = ref.types.uint8; + +const _lf_module = Struct({ + 'name': 'string', + 'description': 'string', + 'version': lf_version_t, + 'identifier': lf_crc_t, + 'index': ref.types.uint32, + 'data': 'pointer', + 'size': ref.refType(ref.types.uint32), +}); + +const _lf_arg = Struct({ + 'arg_type': lf_type, + 'arg_value': lf_value, +}); + +const libflipper = ffi.Library('libflipper', { + + // _lf_device *flipper_attach() + 'flipper_attach': [ 'pointer', [ ] ], + + // lf_return_t lf_invoke(void *device, void *module, lf_function function, lf_type type, void *parameters) + 'lf_invoke': [ lf_return_t, [ 'pointer', 'pointer', lf_function, lf_type, 'pointer' ] ], + + // int lf_bind(void *device, struct _lf_module *module) + 'lf_bind': [ 'int', [ 'pointer', ref.refType(_lf_module) ] ], + + // int lf_ll_append(struct _lf_ll *list, struct _lf_arg *arg, void *destructor) + 'lf_ll_append': [ ref.types.void, [ 'pointer', ref.refType(_lf_arg), 'pointer' ] ], + + // int lf_ll_release(struct _lf_ll **list) + 'lf_ll_release': [ ref.types.void, [ 'pointer' ] ], +}); + +const create_arglist = function(types, args) { + let list_handle = ref.NULL_POINTER; + for(let i = 0; i < args.length; i++) { + const arg = new _lf_arg({ + 'arg_type': _lf_type.indexOf(types[i]), + 'arg_value': args[i], + }); + libflipper.lf_ll_append(list_handle, arg.ref(), ref.NULL_POINTER); + } + return list_handle; +}; + +function Flipper ( ) { + this.device = libflipper.flipper_attach(); +} + +/** + * Given an interface declaration and a module name, return a module object with + * function implementations for controlling Flipper. + * + * The interface declaration must be given node-ffi style as follows: + * + * ```js + * const my_module_interface = { + * 'my_module_function_name': [ RETURN TYPE, [ PARAMETER TYPES ] ], + * }; + * ``` + * + * The types must be represented using the "ref" library, which allows you to express + * types from C using javascript. + * + * As an example, the following will bind a module definition for the LED: + * + * ```js + * // Provides representations of C types. + * const ref = require('ref'); + * const Flipper = require('flipper'); + * + * const led_interface = { + * 'rgb': [ ref.types.void, [ ref.types.uint8, ref.types.uint8, ref.types.uint8 ] ], + * }; + * + * const my_flipper = new Flipper(); + * const led_module_object = my_flipper.bind(led_interface, "led"); + * + * // Now you can execute module functions using the module object + * led_module_object.rgb(0, 10, 0); // Sets the LED to greeen + * ``` + * + * @param iface An object describing the interface of the module to bind to. + * @param name The name of the module loaded on Flipper that we're binding to. + */ +Flipper.prototype.bind = function(iface, name) { + + // Hold a reference to this flipper for inner functions to use. + const self = this; + const module = new _lf_module({ + 'name': name, + 'description': '', + 'version': 0, + 'identifier': 0, + 'index': 0, + 'data': ref.types.NULL_POINTER, + 'size': ref.types.NULL_POINTER, + }); + + // Populates the above module object with metadata. + libflipper.lf_bind(self.device, module.ref()); + + const bindings = {}; + + // For each function in the given interface, generate a proxy for it and attach it to the bindings. + Object.keys(iface || {}).forEach(function (func, i) { + + // Get interface metadata for the current function definition. + const info = iface[func]; + const resultType = info[0]; + const paramTypes = info[1]; + + // Generate a proxy function and assign it to the bindings. + bindings[func] = function() { + if (arguments.length !== paramTypes.length) { + console.log("Expected " + paramTypes.length + " args, got " + arguments.length); + } + + const params = create_arglist(paramTypes, arguments); + const ret = _lf_type.indexOf(resultType); + const result = libflipper.lf_invoke(self.device, module.ref(), i, ret, params); + libflipper.lf_ll_release(params.ref()); + return result; + } + }); + + return bindings; +}; + +module.exports = Flipper; diff --git a/languages/js/index.js b/languages/js/index.js index 39a3a343d..5e0198238 100644 --- a/languages/js/index.js +++ b/languages/js/index.js @@ -1,110 +1,23 @@ -var ffi = require('ffi'); -var ref = require('ref'); -var Struct = require('ref-struct'); - -// typedefs -const lf_version_t = ref.types.uint16; -const lf_crc_t = ref.types.uint16; - -const lf_arg = ref.types.uint32; -const lf_function = ref.types.uint8; -const lf_argc = ref.types.uint8; -const lf_return_t = ref.types.uint32; - -const _lf_type = [ - ref.types.uint8, - ref.types.uint16, - ref.types.uint32 -]; - -const lf_type = ref.types.uint8; - -const _lf_module = Struct({ - 'name': 'string', - 'description': 'string', - 'version' lf_version_t, - 'identifier': lf_crc_t, - 'index': ref.types.uint16, - 'device': 'pointer' -}); - -const libflipper = ffi.Library('libflipper', { - - // _lf_device *flipper_attach() - 'flipper_attach': [ 'pointer', [ ] ], - - 'flipper_select': [ 'int', [ 'pointer' ] ], - - // lf_return_t lf_invoke(struct _lf_module *module, lf_function function, struct _fmr_parameters *parameters) - 'lf_invoke': [ lf_return_t, [ ref.refType(_lf_module), lf_function, 'pointer' ] ], - - // int lf_bind(struct _lf_module *module, String name) - 'lf_bind': [ 'int', [ ref.refType(_lf_module), 'string' ] ], - - 'fmr_build': [ 'pointer', [ lf_argc ] ], - - 'lf_append': [ ref.types.void, [ 'pointer', lf_type, lf_arg ] ], - - // led_configure() - 'led_configure': [ ref.types.void, [ ] ], - - // led_rgb(uint8_t red, uint8_t green, uint8_t blue) - 'led_rgb': [ ref.types.void, [ref.types.uint8, ref.types.uint8, ref.types.uint8 ] ] -}); - -const _create_fmr_parameters = function (paramTypes, args) { - var list = libflipper.fmr_build(0); - - var i, arg, argType; - for (i = 0; i < args.length; i++) { - arg = args[i]; - argType = paramTypes[i]; - libflipper.lf_append(list, _lf_type.indexOf(argType), arg); - } - - return list; -}; - -function Flipper ( ) { - this.device = libflipper.flipper_attach(); -} - -// Using a node-ffi style interface declaration, bind the given interface to Flipper. -Flipper.prototype.bindModule = function(iface, name) { - - // Hold a reference to this flipper for inner functions to use. - var self = this; - - var module = new _lf_module(); - - // Populates the above module object with metadata. - var success = libflipper.lf_bind(module.ref(), name); - - var bindings = {}; - - // For each function in the given interface, generate a proxy for it and attach it to the bindings. - Object.keys(iface || {}).forEach(function (func, i) { - - // Get interface metadata for the current function definition. - var info = iface[func]; - var resultType = info[0]; - var paramTypes = info[1]; - - // Generate a proxy function and assign it to the bindings. - bindings[func] = function() { - libflipper.flipper_select(self.device); - - if (arguments.length !== paramTypes.length) { - console.log("Expected " + paramTypes.length + " args, got " + arguments.length); - } - - var params = _create_fmr_parameters(paramTypes, arguments); - - return libflipper.lf_invoke(module.ref(), i, params); - } - }); - - return bindings; +// This is the entry point for the Flipper Javascript bindings. +// +// The "Flipper" type and all of the standard packages are exported by +// this module for ease of access. All Flipper programs begin by +// creating a Flipper object, followed by the package binding being +// used. An example demonstrating the Led package is shown below: +// +// ```js +// const { Flipper, Led } = require('flipper'); +// +// const flipper = new Flipper(); +// const led = new Led(flipper); +// +// led.rgb(0, 0, 10); // Sets the LED to blue. +// ``` + +const Flipper = require('./flipper'); +const Led = require('./led'); + +module.exports = { + Flipper, + Led, }; - -module.exports = Flipper; diff --git a/languages/js/led.js b/languages/js/led.js new file mode 100644 index 000000000..0bd6b216c --- /dev/null +++ b/languages/js/led.js @@ -0,0 +1,24 @@ +const ref = require('ref'); + +const led_interface = { + // int configure(); + 'configure': [ ref.types.uint32, [ ] ], + + // void rgb(uint8_t red, uint8_t green, uint8_t blue); + 'rgb': [ ref.types.void, [ ref.types.uint8, ref.types.uint8, ref.types.uint8 ] ], +}; + +function Led(flipper) { + this.device = flipper; + this.module = this.device.bind(led_interface, "led"); +} + +Led.prototype.configure = function() { + return this.module.configure(); +}; + +Led.prototype.rgb = function (red, green, blue) { + return this.module.rgb(red, green, blue); +}; + +module.exports = Led; diff --git a/languages/js/package.json b/languages/js/package.json index 141f1b7a9..bbc2823c9 100644 --- a/languages/js/package.json +++ b/languages/js/package.json @@ -1,6 +1,6 @@ { "name": "flipper", - "version": "0.0.0", + "version": "0.0.1", "description": "Javascript bindings for executing modules on Flipper.", "main": "index.js", "dependencies": { @@ -9,9 +9,6 @@ "ref-struct": "^1.1.0" }, "devDependencies": {}, - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, "keywords": [ "flipper" ], diff --git a/languages/js/test.js b/languages/js/test.js index 9dbaab9b9..84e9738a2 100644 --- a/languages/js/test.js +++ b/languages/js/test.js @@ -1,19 +1,9 @@ -/** - * @author Nick Mosher - */ -ref = require('ref'); -Flipper = require('./index.js'); +// This is a test file representing code that a user would write +// to control Flipper. This example demonstrates using the LED. -var flipper = new Flipper(); +const { Flipper, Led } = require('./index'); -const gpioModuleDef = { - 'gpio_configure': [ 'int', [ ] ], - 'gpio_enable': [ ref.types.void, [ ref.types.uint32, ref.types.uint32 ] ], - 'gpio_write': [ ref.types.void, [ ref.types.uint32, ref.types.uint32 ] ] -}; +const flipper = new Flipper(); +const led = new Led(flipper); -var gpioModule = flipper.bindModule(gpioModuleDef, "gpio"); - -gpioModule.gpio_configure(); -gpioModule.gpio_enable(1, 0); -gpioModule.gpio_write(1, 0); +led.rgb(0, 0, 10); diff --git a/languages/python/flipper/lf.py b/languages/python/flipper/lf.py index 26b2fc5ec..cf9a95588 100644 --- a/languages/python/flipper/lf.py +++ b/languages/python/flipper/lf.py @@ -77,7 +77,7 @@ def attach_network(hostname): return libflipper.carbon_attach_hostname(c_char_p(hostname)) def bind(module, device): - libflipper.lf_bind(c_void_p(module.ref), c_void_p(device.ref)) + libflipper.lf_bind(c_void_p(device.ref), c_void_p(module.ref)) def current_device(): libflipper.lf_get_current_device.restype = c_void_p @@ -96,5 +96,5 @@ def getModule(name): return module(name, None, byref(_module)) def invoke(module, function, ret, arguments): - libflipper.lf_invoke(module.ref, c_byte(function), c_byte(ret), lf_ll_from_list(arguments)) + libflipper.lf_invoke(current_device(), module.ref, c_byte(function), c_byte(ret), lf_ll_from_list(arguments)) return diff --git a/languages/rust/examples/led.rs b/languages/rust/examples/led.rs index 723784627..94ea28e55 100644 --- a/languages/rust/examples/led.rs +++ b/languages/rust/examples/led.rs @@ -1,10 +1,10 @@ extern crate flipper; -use flipper::{Flipper, StandardModule}; +use flipper::Flipper; use flipper::fsm::led::Led; fn main() { - Flipper::attach(); - let led = Led::new(); + let flipper = Flipper::attach(); + let led = Led::new(&flipper); led.rgb(10, 0, 0); } diff --git a/languages/rust/examples/module_binding.rs b/languages/rust/examples/module_binding.rs index 6c73bd38b..79328cca9 100644 --- a/languages/rust/examples/module_binding.rs +++ b/languages/rust/examples/module_binding.rs @@ -6,36 +6,39 @@ use flipper::fmr::{ lf_invoke, }; -struct GpioToggle { - ffi: ModuleFFI, +struct GpioToggle<'a> { + flipper: &'a Flipper, + module: ModuleFFI, } -impl<'a> UserModule<'a> for GpioToggle { +impl<'a> UserModule<'a> for GpioToggle<'a> { const NAME: &'a str = "gpio"; - fn new() -> Self { + fn new(flipper: &'a Flipper) -> Self { GpioToggle { - ffi: ModuleFFI::User(UserModuleFFI::uninitialized(Self::NAME)), + flipper, + module: ModuleFFI::User(UserModuleFFI::uninitialized(Self::NAME)), } } } -impl From for GpioToggle { - fn from(user: UserModuleFFI) -> Self { +impl<'a> From<(&'a Flipper, UserModuleFFI)> for GpioToggle<'a> { + fn from((flipper, module): (&'a Flipper, UserModuleFFI)) -> Self { GpioToggle { - ffi: ModuleFFI::User(user), + flipper, + module: ModuleFFI::User(module), } } } -impl GpioToggle { +impl<'a> GpioToggle<'a> { fn toggle(&self) { let args = Args::new().append(4u8); - lf_invoke(&self.ffi, 0, args) + lf_invoke(self.flipper, &self.module, 0, args) } } fn main() { let flipper = Flipper::attach(); - let gpio: GpioToggle = GpioToggle::bind(&flipper); + let gpio: GpioToggle = GpioToggle::new(&flipper); gpio.toggle(); } \ No newline at end of file diff --git a/languages/rust/examples/uart0_binding.rs b/languages/rust/examples/uart0_binding.rs index e595655ed..ed0c26e9c 100644 --- a/languages/rust/examples/uart0_binding.rs +++ b/languages/rust/examples/uart0_binding.rs @@ -1,12 +1,12 @@ extern crate flipper; use std::io::Write; -use flipper::{Flipper, StandardModule}; +use flipper::Flipper; use flipper::fsm::uart0::{Uart0, UartBaud}; fn main() { let flipper = Flipper::attach_hostname("localhost"); - let mut uart = Uart0::bind(&flipper); + let mut uart = Uart0::new(&flipper); uart.configure(&UartBaud::DFU, true); let _ = uart.write(b"deadbeef deadbeef"); } \ No newline at end of file diff --git a/languages/rust/src/fmr.rs b/languages/rust/src/fmr.rs index a5637d461..1dcd046bf 100644 --- a/languages/rust/src/fmr.rs +++ b/languages/rust/src/fmr.rs @@ -11,7 +11,7 @@ use libc; use libc::{c_void, c_int}; use std::ops::Deref; use std::ptr; -use ::{ModuleFFI, _lf_module}; +use ::{Flipper, ModuleFFI, _lf_device, _lf_module}; /// Types transmitted over FMR are encoded in a u8. type _lf_type = libc::uint8_t; @@ -55,9 +55,9 @@ mod libflipper { #[link(name = "flipper")] extern { pub(crate) fn lf_ll_append(ll: *mut *mut _lf_ll, item: *const c_void, destructor: *const c_void) -> c_int; - pub(crate) fn lf_invoke(module: *const _lf_module, function: _lf_index, ret: u8, args: *const _lf_ll) -> _lf_value; - pub(crate) fn lf_push(module: *const _lf_module, function: _lf_index, source: *const c_void, length: u32, args: *const _lf_ll) -> _lf_value; - pub(crate) fn lf_pull(module: *const _lf_module, function: _lf_index, dest: *mut c_void, length: u32, args: *const _lf_ll) -> _lf_value; + pub(crate) fn lf_invoke(device: _lf_device, module: *const _lf_module, function: _lf_index, ret: u8, args: *const _lf_ll) -> _lf_value; + pub(crate) fn lf_push(device: _lf_device, module: *const _lf_module, function: _lf_index, source: *const c_void, length: u32, args: *const _lf_ll) -> _lf_value; + pub(crate) fn lf_pull(device: _lf_device, module: *const _lf_module, function: _lf_index, dest: *mut c_void, length: u32, args: *const _lf_ll) -> _lf_value; } } @@ -228,27 +228,28 @@ impl From for u64 { /// To execute this function using `lf_invoke` would look like this: /// /// ``` -/// use flipper::{ModuleFFI, UserModuleFFI}; +/// use flipper::{Flipper, ModuleFFI, UserModuleFFI}; /// use flipper::fmr::{Args, lf_invoke}; /// /// // Don't do this, this is just to get the doc tests to compile. /// // See how to create a user module. -/// let ffi = ModuleFFI::User(UserModuleFFI::uninitialized("some_module")); +/// let module = ModuleFFI::User(UserModuleFFI::uninitialized("some_module")); /// /// let args = Args::new() /// .append(10 as u16) // bar /// .append(20 as u32) // baz /// .append(30 as u64); // qux /// -/// let output: u8 = lf_invoke(&ffi, 0, args); +/// let flipper = Flipper::attach(); +/// let output: u8 = lf_invoke(&flipper, &module, 0, args); /// ``` -pub fn lf_invoke<'a, T: LfReturnable>(module: &'a ModuleFFI, index: u8, args: Args) -> T { +pub fn lf_invoke(flipper: &Flipper, module: &ModuleFFI, index: u8, args: Args) -> T { unsafe { let mut arglist: *mut _lf_ll = ptr::null_mut(); for arg in args.iter() { libflipper::lf_ll_append(&mut arglist, &arg.0 as *const _lf_arg as *const c_void, ptr::null()); } - let ret = libflipper::lf_invoke(module.as_ptr(), index, T::lf_type(), arglist); + let ret = libflipper::lf_invoke(flipper.device, module.as_ptr(), index, T::lf_type(), arglist); T::from(LfReturn(ret)) } } @@ -259,13 +260,13 @@ pub fn lf_invoke<'a, T: LfReturnable>(module: &'a ModuleFFI, index: u8, args: Ar /// This is currently only used for certain Standard Modules such as uart0 /// for sending and receiving data over a bus. However, it may be expanded /// in the future to support user module functions as well. -pub fn lf_push<'a, T: LfReturnable>(module: &'a ModuleFFI, index: u8, data: &[u8], args: Args) -> T { +pub fn lf_push(flipper: &Flipper, module: &ModuleFFI, index: u8, data: &[u8], args: Args) -> T { unsafe { let mut arglist: *mut _lf_ll = ptr::null_mut(); for arg in args.iter() { libflipper::lf_ll_append(&mut arglist, &arg.0 as *const _lf_arg as *const c_void, ptr::null()); } - let ret = libflipper::lf_push(module.as_ptr(), index, data.as_ptr() as *const c_void, data.len() as u32, arglist); + let ret = libflipper::lf_push(flipper.device, module.as_ptr(), index, data.as_ptr() as *const c_void, data.len() as u32, arglist); T::from(LfReturn(ret)) } } @@ -276,13 +277,13 @@ pub fn lf_push<'a, T: LfReturnable>(module: &'a ModuleFFI, index: u8, data: &[u8 /// This is currently only used for certain Standard Modules such as uart0 /// for sending and receiving data over a bus. However, it may be expanded /// in the future to support user module functions as well. -pub fn lf_pull<'a, T: LfReturnable>(module: &'a ModuleFFI, index: u8, buffer: &mut [u8], args: Args) -> T { +pub fn lf_pull(flipper: &Flipper, module: &ModuleFFI, index: u8, buffer: &mut [u8], args: Args) -> T { unsafe { let mut arglist: *mut _lf_ll = ptr::null_mut(); for arg in args.iter() { libflipper::lf_ll_append(&mut arglist, &arg.0 as *const _lf_arg as *const c_void, ptr::null()); } - let ret = libflipper::lf_pull(module.as_ptr(), index, buffer.as_mut_ptr() as *mut c_void, buffer.len() as u32, arglist); + let ret = libflipper::lf_pull(flipper.device, module.as_ptr(), index, buffer.as_mut_ptr() as *mut c_void, buffer.len() as u32, arglist); T::from(LfReturn(ret)) } } diff --git a/languages/rust/src/fsm/led.rs b/languages/rust/src/fsm/led.rs index 6106dced9..7a28a03ac 100644 --- a/languages/rust/src/fsm/led.rs +++ b/languages/rust/src/fsm/led.rs @@ -2,7 +2,6 @@ use ::{ Flipper, - StandardModule, StandardModuleFFI, ModuleFFI, _lf_module, @@ -18,33 +17,20 @@ extern { static _led: _lf_module; } -pub struct Led { +pub struct Led<'a> { + flipper: &'a Flipper, module: ModuleFFI, } -impl StandardModule for Led { - fn new() -> Self { - unsafe { - let module = StandardModuleFFI { module_meta: &_led }; - Led { - module: ModuleFFI::Standard(module), - } - } +impl<'a> Led<'a> { + pub fn new(flipper: &'a Flipper) -> Self { + let module = unsafe { StandardModuleFFI { module_meta: &_led } }; + let module = ModuleFFI::Standard(module); + Led { flipper, module } } - fn bind(_: &Flipper) -> Self { - unsafe { - let module = StandardModuleFFI { module_meta: &_led }; - Led { - module: ModuleFFI::Standard(module), - } - } - } -} - -impl Led { pub fn configure(&self) { - lf_invoke(&self.module, 0, Args::new()) + lf_invoke(self.flipper, &self.module, 0, Args::new()) } pub fn rgb(&self, r: u8, g: u8, b: u8) { @@ -52,6 +38,6 @@ impl Led { .append(r) .append(g) .append(b); - lf_invoke(&self.module, 1, args) + lf_invoke(self.flipper, &self.module, 1, args) } } diff --git a/languages/rust/src/fsm/uart0.rs b/languages/rust/src/fsm/uart0.rs index fcdff6ff7..dda2a31ef 100644 --- a/languages/rust/src/fsm/uart0.rs +++ b/languages/rust/src/fsm/uart0.rs @@ -4,7 +4,6 @@ use std::io::{Read, Write, Result}; use ::{ Flipper, - StandardModule, ModuleFFI, StandardModuleFFI, _lf_module, @@ -36,59 +35,45 @@ impl UartBaud { } } -pub struct Uart0 { - ffi: ModuleFFI, +pub struct Uart0<'a> { + flipper: &'a Flipper, + module: ModuleFFI, } -impl StandardModule for Uart0 { - fn new() -> Self { - unsafe { - let ffi = StandardModuleFFI { module_meta: &_uart0 }; - Uart0 { - ffi: ModuleFFI::Standard(ffi), - } - } - } - /// Instantiates a Uart0 module bound to a specific Flipper device. - // TODO implement binding - fn bind(_: &Flipper) -> Self { - unsafe { - let ffi = StandardModuleFFI { module_meta: &_uart0 }; - Uart0 { - ffi: ModuleFFI::Standard(ffi), - } - } +impl<'a> Uart0<'a> { + pub fn new(flipper: &'a Flipper) -> Self { + let module = unsafe { StandardModuleFFI { module_meta: &_uart0 } }; + let module = ModuleFFI::Standard(module); + Uart0 { flipper, module } } -} -impl Uart0 { /// Configures the Uart0 module with a given baud rate and /// interrupts enabled flag. pub fn configure(&self, baud: &UartBaud, interrupts: bool) { let args = Args::new() .append(baud.to_baud()) .append(if interrupts { 1u8 } else { 0u8 }); - lf_invoke(&self.ffi, 0, args) + lf_invoke(self.flipper, &self.module, 0, args) } /// Indicates whether the Uart0 bus is ready to read or write. pub fn ready(&self) -> bool { - let ret: u8 = lf_invoke(&self.ffi, 1, Args::new()); + let ret: u8 = lf_invoke(self.flipper, &self.module, 1, Args::new()); ret != 0 } } -impl Write for Uart0 { +impl<'a> Write for Uart0<'a> { fn write(&mut self, buf: &[u8]) -> Result { - lf_push::<()>(&self.ffi, 2, buf, Args::new()); + lf_push::<()>(self.flipper, &self.module, 2, buf, Args::new()); Ok(buf.len()) } fn flush(&mut self) -> Result<()> { Ok(()) } } -impl Read for Uart0 { +impl<'a> Read for Uart0<'a> { fn read(&mut self, buf: &mut [u8]) -> Result { - lf_pull::<()>(&self.ffi, 3, buf, Args::new()); + lf_pull::<()>(self.flipper, &self.module, 3, buf, Args::new()); Ok(buf.len()) } } diff --git a/languages/rust/src/lib.rs b/languages/rust/src/lib.rs index c6931d9c1..75d28782d 100644 --- a/languages/rust/src/lib.rs +++ b/languages/rust/src/lib.rs @@ -132,54 +132,53 @@ pub trait StandardModule { /// When a user creates a module, they give it a name which is used by /// Flipper to load and bind to it. To use it from the Rust bindings, /// the user must specify the name so that rust can find the module. -pub trait UserModule<'a>: From { +pub trait UserModule<'a>: From<(&'a Flipper, UserModuleFFI)> { const NAME: &'a str; - fn new() -> Self; /// Binds an instance of a User Module to the given Flipper. /// /// ``` /// use flipper::{Flipper, UserModule, ModuleFFI, UserModuleFFI}; /// - /// struct MyModule { - /// ffi: ModuleFFI, + /// struct MyModule<'a> { + /// flipper: &'a Flipper, + /// module: ModuleFFI, /// } /// - /// impl<'a> UserModule<'a> for MyModule { + /// impl<'a> UserModule<'a> for MyModule<'a> { /// const NAME: &'a str = "My module"; - /// fn new() -> Self { + /// fn new(flipper: &'a Flipper) -> Self { /// MyModule { - /// ffi: ModuleFFI::User(UserModuleFFI::uninitialized(Self::NAME)), + /// flipper, + /// module: ModuleFFI::User(UserModuleFFI::uninitialized(Self::NAME)), /// } /// } /// } /// - /// impl From for MyModule { - /// fn from(module: UserModuleFFI) -> Self { + /// impl<'a> From<(&'a Flipper, UserModuleFFI)> for MyModule<'a> { + /// fn from((flipper, module): (&'a Flipper, UserModuleFFI)) -> Self { /// MyModule { - /// ffi: ModuleFFI::User(module), + /// flipper, + /// module: ModuleFFI::User(module), /// } /// } /// } /// - /// impl MyModule { + /// impl<'a> MyModule<'a> { /// fn myFunc(&self) { /// // Do FMR invocation /// } /// } /// /// let flipper = Flipper::attach(); - /// - /// // Any of the following will bind "MyModule" - /// let myModule = MyModule::new(); // Attaches to default ("active") flipper - /// let myModule = MyModule::bind(&flipper); // Attaches to specified flipper + /// let myModule = MyModule::new(&flipper); // Binds "MyModule" to control "flipper". /// /// myModule.myFunc(); /// ``` - fn bind(flipper: &Flipper) -> Self { + fn new(flipper: &'a Flipper) -> Self { let mut module = UserModuleFFI::uninitialized(Self::NAME); - unsafe { lf_bind(&mut module.module_meta, flipper.device); } - Self::from(module) + unsafe { lf_bind(flipper.device, &mut module.module_meta); } + Self::from((flipper, module)) } } @@ -187,7 +186,7 @@ pub trait UserModule<'a>: From { extern { fn flipper_attach() -> _lf_device; fn carbon_attach_hostname(hostname: *const c_char) -> _lf_device; - fn lf_bind(module: *mut _lf_module, device: *const c_void) -> c_int; + fn lf_bind(device: *const c_void, module: *mut _lf_module) -> c_int; } pub struct Flipper { diff --git a/library/src/libflipper.c b/library/src/libflipper.c index 35c0cd8dd..63e7386c3 100644 --- a/library/src/libflipper.c +++ b/library/src/libflipper.c @@ -5,12 +5,12 @@ struct _lf_device *lf_current_device; lf_event_list lf_registered_events; /* Creates a new libflipper device. */ -struct _lf_device *lf_device_create(struct _lf_endpoint *endpoint, int (* select)(struct _lf_device *device), int (* destroy)(struct _lf_device *device), size_t context_size) { +struct _lf_device *lf_device_create(struct _lf_endpoint *endpoint, int (* select)(struct _lf_device *device), int (* release)(struct _lf_device *device), size_t context_size) { struct _lf_device *device = (struct _lf_device *)calloc(1, sizeof(struct _lf_device)); lf_assert(device, failure, E_MALLOC, "Failed to allocate memory for new device."); device->endpoint = endpoint; device->select = select; - device->destroy = destroy; + device->release = release; device->_ctx = calloc(1, context_size); return device; failure: @@ -29,7 +29,7 @@ struct _lf_device *lf_get_current_device(void) { int lf_device_release(struct _lf_device *device) { if (device) { lf_endpoint_release(device->endpoint); - if (device->destroy) device->destroy(device); + if (device->release) device->release(device); free(device->_ctx); free(device); } @@ -74,20 +74,19 @@ int __attribute__((__destructor__)) lf_exit(void) { } /* Binds the lf_module structure to its counterpart on the attached device. */ -LF_WEAK int lf_bind(struct _lf_module *module, struct _lf_device *device) { +LF_WEAK int lf_bind(struct _lf_device *device, struct _lf_module *module) { lf_assert(module, failure, E_MODULE, "NULL module passed to '%s'.", __PRETTY_FUNCTION__); lf_assert(device, failure, E_NULL, "NULL device passed to '%s'.", __PRETTY_FUNCTION__) lf_assert(module->name, failure, E_MODULE, "Module has no name."); lf_debug("Binding to module '%s'.", module->name); - module->device = device; module->identifier = lf_crc(module->name, strlen(module->name) + 1); int index = fld_index(module->identifier); if (index == -1) { lf_debug("Could not find counterpart for '%s'. Attempting to load it.", module->name); - lf_load(module->data, *module->psize, module->device); + lf_load(device, module->data, *module->psize); index = fld_index(module->identifier); } - lf_assert(index != -1, failure, E_MODULE, "No counterpart for the module '%s' was found on the device '%s'. Load the module first.", module->name, module->device->configuration.name); + lf_assert(index != -1, failure, E_MODULE, "No counterpart for the module '%s' was found on the device '%s'. Load the module first.", module->name, device->configuration.name); module->index = index | FMR_USER_INVOCATION_BIT; return lf_success; failure: diff --git a/runtime/include/flipper/libflipper.h b/runtime/include/flipper/libflipper.h index 592504bb8..401956355 100644 --- a/runtime/include/flipper/libflipper.h +++ b/runtime/include/flipper/libflipper.h @@ -105,7 +105,7 @@ struct _lf_device { /* The device's selector function. Mutates modules state as appropriate for the device. */ int (* select)(struct _lf_device *device); /* The device's destructor. */ - int (* destroy)(struct _lf_device *device); + int (* release)(struct _lf_device *device); /* The device's context. */ void *_ctx; /* The current error state of the device. */ @@ -135,8 +135,6 @@ struct _lf_module { lf_crc_t identifier; /*! The module's loaded index. */ int index; - /*! The pointer to a pointer to the device upon which the module's counterpart is located. */ - struct _lf_device *device; /*! The module's binary data. */ void *data; /*! The binary data size. */ @@ -151,14 +149,11 @@ struct _lf_module { LF_VERSION, \ 0, \ -1, \ - NULL, \ pdata, \ plen \ }; -#define LF_MODULE_SET_DEVICE_AND_ID(module, _device, _id) do { module.device = _device; module.index = _id; } while (0); - -struct _lf_device *lf_device_create(struct _lf_endpoint *endpoint, int (* select)(struct _lf_device *device), int (* destroy)(struct _lf_device *device), size_t context_size); +struct _lf_device *lf_device_create(struct _lf_endpoint *endpoint, int (* select)(struct _lf_device *device), int (* release)(struct _lf_device *device), size_t context_size); int lf_device_release(struct _lf_device *device); /* Attaches to a device. */ @@ -171,11 +166,11 @@ int lf_select(struct _lf_device *device); #include /* Performs a remote procedure call to a module's function. */ -lf_return_t lf_invoke(struct _lf_module *module, lf_function function, lf_type ret, struct _lf_ll *args); +lf_return_t lf_invoke(struct _lf_device *device, struct _lf_module *module, lf_function function, lf_type ret, struct _lf_ll *args); /* Moves data from the address space of the host to that of the device. */ -lf_return_t lf_push(struct _lf_module *module, lf_function function, void *source, lf_size_t length, struct _lf_ll *args); +lf_return_t lf_push(struct _lf_device *device, struct _lf_module *module, lf_function function, void *source, lf_size_t length, struct _lf_ll *args); /* Moves data from the address space of the device to that of the host. */ -lf_return_t lf_pull(struct _lf_module *module, lf_function function, void *destination, lf_size_t length, struct _lf_ll *args); +lf_return_t lf_pull(struct _lf_device *device, struct _lf_module *module, lf_function function, void *destination, lf_size_t length, struct _lf_ll *args); /* Closes the library. */ int lf_exit(void); @@ -192,10 +187,10 @@ int lf_transfer(struct _lf_device *device, struct _fmr_packet *packet); /* Retrieves a packet from the specified device. */ int lf_retrieve(struct _lf_device *device, struct _fmr_result *response); /* Binds a module structure to its device counterpart. */ -int lf_bind(struct _lf_module *module, struct _lf_device *device); +int lf_bind(struct _lf_device *device, struct _lf_module *module); /* Experimental: Load an application into RAM and execute it. */ -int lf_load(void *source, lf_size_t length, struct _lf_device *device); +int lf_load(struct _lf_device *device, void *source, lf_size_t length); /* Prints verbose information about the packet disassembly. */ void lf_debug_packet(struct _fmr_packet *packet, size_t length); diff --git a/runtime/src/adc.c b/runtime/src/adc.c index cb82a03a3..2e2b54f81 100644 --- a/runtime/src/adc.c +++ b/runtime/src/adc.c @@ -10,7 +10,7 @@ const struct _adc_interface adc = { }; LF_WEAK int adc_configure(void) { - return lf_invoke(&_adc, _adc_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_adc, _adc_configure, lf_int_t, NULL); } #endif diff --git a/runtime/src/button.c b/runtime/src/button.c index 02ee6b91b..7efa13348 100644 --- a/runtime/src/button.c +++ b/runtime/src/button.c @@ -11,11 +11,11 @@ const struct _button_interface button = { }; LF_WEAK int button_configure(void) { - return lf_invoke(&_button, _button_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_button, _button_configure, lf_int_t, NULL); } LF_WEAK uint8_t button_read(void) { - return lf_invoke(&_button, _button_read, lf_int8_t, NULL); + return lf_invoke(lf_get_current_device(), &_button, _button_read, lf_int8_t, NULL); } #endif diff --git a/runtime/src/dac.c b/runtime/src/dac.c index 3153b1905..69c7d8f5c 100644 --- a/runtime/src/dac.c +++ b/runtime/src/dac.c @@ -10,7 +10,7 @@ const struct _dac_interface dac = { }; LF_WEAK int dac_configure(void) { - return lf_invoke(&_dac, _dac_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_dac, _dac_configure, lf_int_t, NULL); } #endif diff --git a/runtime/src/fld.c b/runtime/src/fld.c index 9bdcca064..aec1f995e 100644 --- a/runtime/src/fld.c +++ b/runtime/src/fld.c @@ -11,11 +11,11 @@ const struct _fld_interface fld = { }; LF_WEAK int fld_configure(void) { - return lf_invoke(&_fld, _fld_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_fld, _fld_configure, lf_int_t, NULL); } LF_WEAK int fld_index(lf_crc_t identifier) { - return lf_invoke(&_fld, _fld_index, lf_int_t, lf_args(lf_infer(identifier))); + return lf_invoke(lf_get_current_device(), &_fld, _fld_index, lf_int_t, lf_args(lf_infer(identifier))); } #endif diff --git a/runtime/src/gpio.c b/runtime/src/gpio.c index f47a449cf..14744ba6d 100644 --- a/runtime/src/gpio.c +++ b/runtime/src/gpio.c @@ -13,19 +13,19 @@ const struct _gpio_interface gpio = { }; LF_WEAK int gpio_configure(void) { - return lf_invoke(&_gpio, _gpio_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_gpio, _gpio_configure, lf_int_t, NULL); } LF_WEAK void gpio_enable(uint32_t enable, uint32_t disable) { - lf_invoke(&_gpio, _gpio_enable, lf_void_t, lf_args(lf_infer(enable), lf_infer(disable))); + lf_invoke(lf_get_current_device(), &_gpio, _gpio_enable, lf_void_t, lf_args(lf_infer(enable), lf_infer(disable))); } LF_WEAK void gpio_write(uint32_t set, uint32_t clear) { - lf_invoke(&_gpio, _gpio_write, lf_void_t, lf_args(lf_infer(set), lf_infer(clear))); + lf_invoke(lf_get_current_device(), &_gpio, _gpio_write, lf_void_t, lf_args(lf_infer(set), lf_infer(clear))); } LF_WEAK uint32_t gpio_read(uint32_t mask) { - return lf_invoke(&_gpio, _gpio_read, lf_int32_t, lf_args(lf_infer(mask))); + return lf_invoke(lf_get_current_device(), &_gpio, _gpio_read, lf_int32_t, lf_args(lf_infer(mask))); } #endif diff --git a/runtime/src/i2c.c b/runtime/src/i2c.c index 4b195ef49..482ee22fc 100644 --- a/runtime/src/i2c.c +++ b/runtime/src/i2c.c @@ -10,7 +10,7 @@ const struct _i2c_interface i2c = { }; LF_WEAK int i2c_configure(void) { - return lf_invoke(&_i2c, _i2c_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_i2c, _i2c_configure, lf_int_t, NULL); } #endif diff --git a/runtime/src/led.c b/runtime/src/led.c index 5a9c11386..a96c6b52a 100644 --- a/runtime/src/led.c +++ b/runtime/src/led.c @@ -11,12 +11,12 @@ const struct _led_interface led = { }; LF_WEAK int led_configure(void) { - lf_invoke(&_led, _led_configure, lf_int_t, NULL); + lf_invoke(lf_get_current_device(), &_led, _led_configure, lf_int_t, NULL); return lf_success; } LF_WEAK void led_rgb(uint8_t r, uint8_t g, uint8_t b) { - lf_invoke(&_led, _led_rgb, lf_void_t, lf_args(lf_infer(r), lf_infer(g), lf_infer(b))); + lf_invoke(lf_get_current_device(), &_led, _led_rgb, lf_void_t, lf_args(lf_infer(r), lf_infer(g), lf_infer(b))); } #endif diff --git a/runtime/src/pwm.c b/runtime/src/pwm.c index 5513aeb4a..f2c1cc833 100644 --- a/runtime/src/pwm.c +++ b/runtime/src/pwm.c @@ -10,7 +10,7 @@ const struct _pwm_interface pwm = { }; LF_WEAK int pwm_configure(void) { - return lf_invoke(&_pwm, _pwm_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_pwm, _pwm_configure, lf_int_t, NULL); } #endif diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index b1211e920..825c45373 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -28,19 +28,12 @@ int lf_retrieve(struct _lf_device *device, struct _fmr_result *result) { return lf_error; } -lf_return_t lf_invoke(struct _lf_module *module, lf_function function, lf_type ret, struct _lf_ll *parameters) { - lf_assert(module, failure, E_NULL, "No module was specified for function invocation."); - - /* If the module has no device, assume the invocation is for the current device. */ - if (!module->device) { - lf_debug("No device specified for module %s, using current device.", module->name); - module->device = lf_get_current_device(); - } - - lf_assert(module->device, failure, E_NO_DEVICE, "The module '%s' has no target device. Did you attach?", module->name); +lf_return_t lf_invoke(struct _lf_device *device, struct _lf_module *module, lf_function function, lf_type ret, struct _lf_ll *parameters) { + lf_assert(device, failure, E_NULL, "No device was provided to '%s'.", __PRETTY_FUNCTION__); + lf_assert(module, failure, E_NULL, "No module was provided to '%s'.", __PRETTY_FUNCTION__); /* If the module has no index, try to bind it. */ - if (module->index == -1) lf_bind(module, module->device); + if (module->index == -1) lf_bind(device, module); /* The raw packet into which the invocation information will be loaded .*/ struct _fmr_packet _packet; @@ -63,21 +56,24 @@ lf_return_t lf_invoke(struct _lf_module *module, lf_function function, lf_type r lf_assert(_e == lf_success, failure, E_NULL, "Failed to generate a valid call to module '%s'.", module->name); _packet.header.checksum = lf_crc(&_packet, _packet.header.length); - _e = lf_transfer(module->device, &_packet); + _e = lf_transfer(device, &_packet); lf_assert(_e == lf_success, failure, E_FMR, "Failed to transfer command to module '%s'.", module->name); struct _fmr_result result; - lf_get_result(module->device, &result); + lf_get_result(device, &result); return result.value; failure: return -1; } -lf_return_t lf_push(struct _lf_module *module, lf_function function, void *source, lf_size_t length, struct _lf_ll *parameters) { - lf_assert(module, failure, E_NULL, "NULL module was specified for data push."); - lf_assert(module->index != -1, failure, E_MODULE, "The module '%s' has not been configured. Call '%s_configure()' first.", module->name, module->name); - lf_assert(module->device, failure, E_NO_DEVICE, "The module '%s' has no target device. Did you attach before configuring?", module->name); +lf_return_t lf_push(struct _lf_device *device, struct _lf_module *module, lf_function function, void *source, lf_size_t length, struct _lf_ll *parameters) { + lf_assert(device, failure, E_NULL, "No device was provided to '%s'.", __PRETTY_FUNCTION__); + lf_assert(module, failure, E_NULL, "No module was provided to '%s'.", __PRETTY_FUNCTION__); + + /* If the module has no index, try to bind it. */ + if (module->index == -1) lf_bind(device, module); + if (!length) return lf_success; struct _fmr_packet _packet; @@ -93,25 +89,28 @@ lf_return_t lf_push(struct _lf_module *module, lf_function function, void *sourc _packet.header.checksum = lf_crc(packet, _packet.header.length); /* Send the packet to the target device. */ - _e = lf_transfer(module->device, &_packet); + _e = lf_transfer(device, &_packet); lf_assert(_e == lf_success, failure, E_FMR, "Failed to transfer push command to module '%s'.", module->name); /* Transfer the data through to the address space of the device. */ - _e = module->device->endpoint->push(module->device->endpoint, source, length); + _e = device->endpoint->push(device->endpoint, source, length); lf_assert(_e == lf_success, failure, E_FMR, "Failed to push data to module '%s'.", module->name); struct _fmr_result result; - lf_get_result(module->device, &result); + lf_get_result(device, &result); return result.value; failure: return lf_error; } -lf_return_t lf_pull(struct _lf_module *module, lf_function function, void *destination, lf_size_t length, struct _lf_ll *parameters) { - lf_assert(module, failure, E_NULL, "NULL module was specified for data pull."); - lf_assert(module->index != -1, failure, E_MODULE, "The module '%s' has not been configured. Call '%s_configure()' first.", module->name, module->name); - lf_assert(module->device, failure, E_NO_DEVICE, "The module '%s' has no target device. Did you attach before configuring?", module->name); +lf_return_t lf_pull(struct _lf_device *device, struct _lf_module *module, lf_function function, void *destination, lf_size_t length, struct _lf_ll *parameters) { + lf_assert(device, failure, E_NULL, "No device was provided to '%s'.", __PRETTY_FUNCTION__); + lf_assert(module, failure, E_NULL, "No module was provided to '%s'.", __PRETTY_FUNCTION__); + + /* If the module has no index, try to bind it. */ + if (module->index == -1) lf_bind(device, module); + if (!length) return lf_success; struct _fmr_packet _packet; @@ -128,25 +127,25 @@ lf_return_t lf_pull(struct _lf_module *module, lf_function function, void *desti _packet.header.checksum = lf_crc(packet, _packet.header.length); /* Send the packet to the target device. */ - _e = lf_transfer(module->device, &_packet); + _e = lf_transfer(device, &_packet); lf_assert(_e == lf_success, failure, E_FMR, "Failed to transfer pull command to module '%s'.", module->name); /* Obtain the data from the address space of the device. */ - _e = module->device->endpoint->pull(module->device->endpoint, destination, length); + _e = device->endpoint->pull(device->endpoint, destination, length); lf_assert(_e == lf_success, failure, E_FMR, "Failed to pull data from module '%s'.", module->name); struct _fmr_result result; - lf_get_result(module->device, &result); + lf_get_result(device, &result); return result.value; failure: return lf_error; } -int lf_load(void *source, lf_size_t length, struct _lf_device *device) { - lf_assert(device, failure, E_NULL, "No device specified for RAM load."); - lf_assert(source, failure, E_NULL, "No source specified for RAM load to device '%s'.", device->configuration.name); - lf_assert(length, failure, E_NULL, "No length specified for RAM load to device '%s'.", device->configuration.name); +int lf_load(struct _lf_device *device, void *source, lf_size_t length) { + lf_assert(device, failure, E_NULL, "No device was provided to '%s'.", __PRETTY_FUNCTION__); + lf_assert(source, failure, E_NULL, "No source was provided to '%s'.", __PRETTY_FUNCTION__); + lf_assert(length, failure, E_NULL, "No length was provided to '%s'.", __PRETTY_FUNCTION__); struct _fmr_packet _packet; memset(&_packet, 0, sizeof(struct _fmr_packet)); diff --git a/runtime/src/spi.c b/runtime/src/spi.c index b567893d5..3469ddde2 100644 --- a/runtime/src/spi.c +++ b/runtime/src/spi.c @@ -17,35 +17,35 @@ const struct _spi_interface spi = { }; LF_WEAK int spi_configure() { - return lf_invoke(&_spi, _spi_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_spi, _spi_configure, lf_int_t, NULL); } LF_WEAK void spi_enable(void) { - lf_invoke(&_spi, _spi_enable, lf_int_t, NULL); + lf_invoke(lf_get_current_device(), &_spi, _spi_enable, lf_int_t, NULL); } LF_WEAK void spi_disable(void) { - lf_invoke(&_spi, _spi_disable, lf_int_t, NULL); + lf_invoke(lf_get_current_device(), &_spi, _spi_disable, lf_int_t, NULL); } LF_WEAK uint8_t spi_ready(void) { - return lf_invoke(&_spi, _spi_ready, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_spi, _spi_ready, lf_int_t, NULL); } LF_WEAK void spi_put(uint8_t byte) { - lf_invoke(&_spi, _spi_put, lf_int_t, lf_args(lf_infer(byte))); + lf_invoke(lf_get_current_device(), &_spi, _spi_put, lf_int_t, lf_args(lf_infer(byte))); } LF_WEAK uint8_t spi_get(void) { - return lf_invoke(&_spi, _spi_get, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_spi, _spi_get, lf_int_t, NULL); } LF_WEAK int spi_push(void *source, uint32_t length) { - return lf_push(&_spi, _spi_push, source, length, NULL); + return lf_push(lf_get_current_device(), &_spi, _spi_push, source, length, NULL); } LF_WEAK int spi_pull(void *destination, uint32_t length) { - return lf_pull(&_spi, _spi_pull, destination, length, NULL); + return lf_pull(lf_get_current_device(), &_spi, _spi_pull, destination, length, NULL); } #endif diff --git a/runtime/src/swd.c b/runtime/src/swd.c index 22beb25d7..10ba4e182 100644 --- a/runtime/src/swd.c +++ b/runtime/src/swd.c @@ -10,7 +10,7 @@ const struct _swd_interface swd = { }; LF_WEAK int swd_configure(void) { - return lf_invoke(&_swd, _swd_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_swd, _swd_configure, lf_int_t, NULL); } #endif diff --git a/runtime/src/task.c b/runtime/src/task.c index 236302028..a34d6a861 100644 --- a/runtime/src/task.c +++ b/runtime/src/task.c @@ -12,15 +12,15 @@ const struct _task_interface task = { }; LF_WEAK int os_task_pause(int pid) { - return lf_invoke(&_task, _task_pause, lf_int_t, lf_args(lf_infer(pid))); + return lf_invoke(lf_get_current_device(), &_task, _task_pause, lf_int_t, lf_args(lf_infer(pid))); } LF_WEAK int os_task_resume(int pid) { - return lf_invoke(&_task, _task_resume, lf_int_t, lf_args(lf_infer(pid))); + return lf_invoke(lf_get_current_device(), &_task, _task_resume, lf_int_t, lf_args(lf_infer(pid))); } LF_WEAK int os_task_stop(int pid) { - return lf_invoke(&_task, _task_stop, lf_int_t, lf_args(lf_infer(pid))); + return lf_invoke(lf_get_current_device(), &_task, _task_stop, lf_int_t, lf_args(lf_infer(pid))); } #endif diff --git a/runtime/src/temp.c b/runtime/src/temp.c index 5e90e3e62..c9ad2aeb4 100644 --- a/runtime/src/temp.c +++ b/runtime/src/temp.c @@ -10,7 +10,7 @@ const struct _temp_interface temp = { }; LF_WEAK int temp_configure(void) { - return lf_invoke(&_temp, _temp_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_temp, _temp_configure, lf_int_t, NULL); } #endif diff --git a/runtime/src/timer.c b/runtime/src/timer.c index 2ab05d498..b7820cc2c 100644 --- a/runtime/src/timer.c +++ b/runtime/src/timer.c @@ -10,7 +10,7 @@ const struct _timer_interface timer = { }; LF_WEAK int timer_configure(void) { - return lf_invoke(&_timer, _timer_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_timer, _timer_configure, lf_int_t, NULL); } #endif diff --git a/runtime/src/uart0.c b/runtime/src/uart0.c index e6200466c..7b3ed5f06 100644 --- a/runtime/src/uart0.c +++ b/runtime/src/uart0.c @@ -13,20 +13,20 @@ const struct _uart0_interface uart0 = { }; LF_WEAK int uart0_configure(uint8_t baud, uint8_t interrupts) { - lf_invoke(&_uart0, _uart0_configure, lf_int_t, lf_args(lf_infer(baud), lf_infer(interrupts))); + lf_invoke(lf_get_current_device(), &_uart0, _uart0_configure, lf_int_t, lf_args(lf_infer(baud), lf_infer(interrupts))); return lf_success; } LF_WEAK int uart0_ready(void) { - return lf_invoke(&_uart0, _uart0_ready, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_uart0, _uart0_ready, lf_int_t, NULL); } LF_WEAK int uart0_push(void *source, lf_size_t length) { - return lf_push(&_uart0, _uart0_push, source, length, NULL); + return lf_push(lf_get_current_device(), &_uart0, _uart0_push, source, length, NULL); } LF_WEAK int uart0_pull(void *destination, lf_size_t length) { - return lf_pull(&_uart0, _uart0_pull, destination, length, NULL); + return lf_pull(lf_get_current_device(), &_uart0, _uart0_pull, destination, length, NULL); } #endif diff --git a/runtime/src/usart.c b/runtime/src/usart.c index c746b113e..9168ec852 100644 --- a/runtime/src/usart.c +++ b/runtime/src/usart.c @@ -13,20 +13,20 @@ const struct _usart_interface usart = { }; LF_WEAK int usart_configure(void) { - lf_invoke(&_usart, _usart_configure, lf_int_t, NULL); + lf_invoke(lf_get_current_device(), &_usart, _usart_configure, lf_int_t, NULL); return lf_success; } LF_WEAK int usart_ready(void) { - return lf_invoke(&_usart, _usart_ready, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_usart, _usart_ready, lf_int_t, NULL); } LF_WEAK int usart_push(void *source, lf_size_t length) { - return lf_push(&_usart, _usart_push, source, length, NULL); + return lf_push(lf_get_current_device(), &_usart, _usart_push, source, length, NULL); } LF_WEAK int usart_pull(void *destination, lf_size_t length) { - return lf_pull(&_usart, _usart_pull, destination, length, NULL); + return lf_pull(lf_get_current_device(), &_usart, _usart_pull, destination, length, NULL); } #endif diff --git a/runtime/src/wdt.c b/runtime/src/wdt.c index 15fc7787a..613664ede 100644 --- a/runtime/src/wdt.c +++ b/runtime/src/wdt.c @@ -11,11 +11,11 @@ const struct _wdt_interface wdt = { }; LF_WEAK int wdt_configure(void) { - return lf_invoke(&_wdt, _wdt_configure, lf_int_t, NULL); + return lf_invoke(lf_get_current_device(), &_wdt, _wdt_configure, lf_int_t, NULL); } LF_WEAK void wdt_fire(void) { - lf_invoke(&_wdt, _wdt_fire, lf_int_t, NULL); + lf_invoke(lf_get_current_device(), &_wdt, _wdt_fire, lf_int_t, NULL); } #endif diff --git a/utils/fdwarf/fdwarf.py b/utils/fdwarf/fdwarf.py index b019ca6d0..085b0a32b 100644 --- a/utils/fdwarf/fdwarf.py +++ b/utils/fdwarf/fdwarf.py @@ -110,7 +110,7 @@ def generate_c(modulename, outputname, functions): for p in f.parameters: args.append("lf_infer(%s)" % p.name) retl = ["lf_void_t", "", "lf_int8_t", "lf_int16_t", "", "lf_int32_t"] - statement = "lf_invoke(&_module, %s, %s, lf_args(%s));" % ("_" + modulename + "_" + f.name, retl[f.ret + 1], ", ".join(args)) + statement = "lf_invoke(lf_get_current_device(), &_module, %s, %s, lf_args(%s));" % ("_" + modulename + "_" + f.name, retl[f.ret + 1], ", ".join(args)) if f.type == "void": body = statement ret = ";" diff --git a/utils/fload/src/main.c b/utils/fload/src/main.c index d5a2246d5..2be6c8fb4 100644 --- a/utils/fload/src/main.c +++ b/utils/fload/src/main.c @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) { fclose(fp); /* Load the application into RAM. */ - lf_return_t value = lf_load(fbuf, fsize, device); + lf_return_t value = lf_load(device, fbuf, fsize); if ((int32_t)value == -1) { fprintf(stderr, "Failed to load application into RAM.\n"); free(fbuf);