summaryrefslogtreecommitdiff
path: root/shared-bindings
diff options
context:
space:
mode:
authorScott Shawcroft <scott@tannewt.org>2018-11-30 14:40:01 -0800
committerScott Shawcroft <scott@tannewt.org>2018-11-30 14:40:01 -0800
commit95e03092630bbad9949c5fe32cd51e7c29bc065b (patch)
tree484cb7535142eaabe873bc10552bbfa1b48ab43b /shared-bindings
parent754d6afd163ae5f295444166863b5d11afd1b2e4 (diff)
parentab94344baee1a5d73d3890de16319cab1e2616de (diff)
Merge remote-tracking branch 'adafruit/master' into mini_sam
Diffstat (limited to 'shared-bindings')
-rw-r--r--shared-bindings/audioio/AudioOut.c9
-rw-r--r--shared-bindings/audioio/AudioOut.h2
-rw-r--r--shared-bindings/audioio/Mixer.c249
-rw-r--r--shared-bindings/audioio/Mixer.h52
-rw-r--r--shared-bindings/audioio/WaveFile.c39
-rw-r--r--shared-bindings/audioio/WaveFile.h2
-rw-r--r--shared-bindings/audioio/__init__.c4
-rw-r--r--shared-bindings/bleio/Adapter.c15
-rw-r--r--shared-bindings/bleio/Adapter.h4
-rw-r--r--shared-bindings/bleio/Address.c167
-rw-r--r--shared-bindings/bleio/Address.h34
-rw-r--r--shared-bindings/bleio/AddressType.c99
-rw-r--r--shared-bindings/bleio/AddressType.h50
-rw-r--r--shared-bindings/bleio/AdvertisementData.c90
-rw-r--r--shared-bindings/bleio/AdvertisementData.h34
-rw-r--r--shared-bindings/bleio/Characteristic.c332
-rw-r--r--shared-bindings/bleio/Characteristic.h38
-rw-r--r--shared-bindings/bleio/Descriptor.c171
-rw-r--r--shared-bindings/bleio/Descriptor.h40
-rw-r--r--shared-bindings/bleio/Device.c357
-rw-r--r--shared-bindings/bleio/Device.h42
-rw-r--r--shared-bindings/bleio/ScanEntry.c308
-rw-r--r--shared-bindings/bleio/ScanEntry.h35
-rw-r--r--shared-bindings/bleio/Scanner.c162
-rw-r--r--shared-bindings/bleio/Scanner.h39
-rw-r--r--shared-bindings/bleio/Service.c170
-rw-r--r--shared-bindings/bleio/Service.h37
-rw-r--r--shared-bindings/bleio/UUID.c146
-rw-r--r--shared-bindings/bleio/UUID.h39
-rw-r--r--shared-bindings/bleio/UUIDType.c75
-rw-r--r--shared-bindings/bleio/UUIDType.h46
-rw-r--r--shared-bindings/bleio/__init__.c42
-rw-r--r--shared-bindings/busio/SPI.c15
-rw-r--r--shared-bindings/busio/SPI.h3
-rw-r--r--shared-bindings/help.c11
-rw-r--r--shared-bindings/network/__init__.c74
-rw-r--r--shared-bindings/network/__init__.h31
-rw-r--r--shared-bindings/pulseio/PWMOut.c2
-rw-r--r--shared-bindings/pulseio/PulseOut.c7
-rw-r--r--shared-bindings/socket/__init__.c559
-rwxr-xr-xshared-bindings/supervisor/Runtime.c26
-rwxr-xr-xshared-bindings/supervisor/Runtime.h2
-rw-r--r--shared-bindings/time/__init__.c14
-rw-r--r--shared-bindings/usb_hid/Device.h2
-rw-r--r--shared-bindings/wiznet/__init__.c69
-rw-r--r--shared-bindings/wiznet/wiznet5k.c183
46 files changed, 3888 insertions, 39 deletions
diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c
index db5b371e2..18d908eef 100644
--- a/shared-bindings/audioio/AudioOut.c
+++ b/shared-bindings/audioio/AudioOut.c
@@ -43,13 +43,15 @@
//|
//| AudioOut can be used to output an analog audio signal on a given pin.
//|
-//| .. class:: AudioOut(left_channel, right_channel=None)
+//| .. class:: AudioOut(left_channel, *, right_channel=None, quiescent_value=0x8000)
//|
//| Create a AudioOut object associated with the given pin(s). This allows you to
//| play audio signals out on the given pin(s).
//|
//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to
//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to
+//| :param int quiescent_value: The output value when no signal is present. Samples should start
+//| and end with this value to prevent audible popping.
//|
//| Simple 8ksps 440 Hz sin wave::
//|
@@ -95,10 +97,11 @@ STATIC mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar
mp_arg_check_num(n_args, n_kw, 1, 2, true);
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
- enum { ARG_left_channel, ARG_right_channel };
+ enum { ARG_left_channel, ARG_right_channel, ARG_quiescent_value };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_left_channel, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_right_channel, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = mp_const_none} },
+ { MP_QSTR_quiescent_value, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_int = 0x8000} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -117,7 +120,7 @@ STATIC mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar
// create AudioOut object from the given pin
audioio_audioout_obj_t *self = m_new_obj(audioio_audioout_obj_t);
self->base.type = &audioio_audioout_type;
- common_hal_audioio_audioout_construct(self, left_channel_pin, right_channel_pin);
+ common_hal_audioio_audioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int);
return MP_OBJ_FROM_PTR(self);
}
diff --git a/shared-bindings/audioio/AudioOut.h b/shared-bindings/audioio/AudioOut.h
index 751473605..d09a5c9ca 100644
--- a/shared-bindings/audioio/AudioOut.h
+++ b/shared-bindings/audioio/AudioOut.h
@@ -35,7 +35,7 @@ extern const mp_obj_type_t audioio_audioout_type;
// left_channel will always be non-NULL but right_channel may be for mono output.
void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self,
- const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel);
+ const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t default_value);
void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self);
bool common_hal_audioio_audioout_deinited(audioio_audioout_obj_t* self);
diff --git a/shared-bindings/audioio/Mixer.c b/shared-bindings/audioio/Mixer.c
new file mode 100644
index 000000000..dc7a12ebc
--- /dev/null
+++ b/shared-bindings/audioio/Mixer.c
@@ -0,0 +1,249 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "shared-bindings/audioio/Mixer.h"
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/binary.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/audioio/RawSample.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: audioio
+//|
+//| :class:`Mixer` -- Mixes one or more audio samples together
+//| ===========================================================
+//|
+//| Mixer mixes multiple samples into one sample.
+//|
+//| .. class:: Mixer(channel_count=2, buffer_size=1024)
+//|
+//| Create a Mixer object that can mix multiple channels with the same sample rate.
+//|
+//| :param int channel_count: The maximum number of samples to mix at once
+//| :param int buffer_size: The total size in bytes of the buffers to mix into
+//|
+//| Playing a wave file from flash::
+//|
+//| import board
+//| import audioio
+//| import digitalio
+//|
+//| # Required for CircuitPlayground Express
+//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
+//| speaker_enable.switch_to_output(value=True)
+//|
+//| music = audioio.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb"))
+//| drum = audioio.WaveFile(open("drum.wav", "rb"))
+//| mixer = audioio.Mixer(voice_count=2, sample_rate=16000, channel_count=1, bits_per_sample=16, samples_signed=True)
+//| a = audioio.AudioOut(board.A0)
+//|
+//| print("playing")
+//| a.play(mixer)
+//| mixer.play(music, voice=0)
+//| while mixer.playing:
+//| mixer.play(drum, voice=1)
+//| time.sleep(1)
+//| print("stopped")
+//|
+STATIC mp_obj_t audioio_mixer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 0, 2, true);
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+ enum { ARG_voice_count, ARG_buffer_size, ARG_channel_count, ARG_bits_per_sample, ARG_samples_signed, ARG_sample_rate };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_voice_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 2} },
+ { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1024} },
+ { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 2} },
+ { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} },
+ { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
+ { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_int_t voice_count = args[ARG_voice_count].u_int;
+ if (voice_count < 1 || voice_count > 255) {
+ mp_raise_ValueError(translate("Invalid voice count"));
+ }
+
+ mp_int_t channel_count = args[ARG_channel_count].u_int;
+ if (channel_count < 1 || channel_count > 2) {
+ mp_raise_ValueError(translate("Invalid channel count"));
+ }
+ mp_int_t sample_rate = args[ARG_sample_rate].u_int;
+ if (sample_rate < 1) {
+ mp_raise_ValueError(translate("Sample rate must be positive"));
+ }
+ mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int;
+ if (bits_per_sample != 8 && bits_per_sample != 16) {
+ mp_raise_ValueError(translate("bits_per_sample must be 8 or 16"));
+ }
+ audioio_mixer_obj_t *self = m_new_obj_var(audioio_mixer_obj_t, audioio_mixer_voice_t, voice_count);
+ self->base.type = &audioio_mixer_type;
+ common_hal_audioio_mixer_construct(self, voice_count, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| Deinitialises the Mixer and releases any hardware resources for reuse.
+//|
+STATIC mp_obj_t audioio_mixer_deinit(mp_obj_t self_in) {
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_audioio_mixer_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_deinit_obj, audioio_mixer_deinit);
+
+//| .. method:: __enter__()
+//|
+//| No-op used by Context Managers.
+//|
+// Provided by context manager helper.
+
+//| .. method:: __exit__()
+//|
+//| Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+STATIC mp_obj_t audioio_mixer_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_audioio_mixer_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_mixer___exit___obj, 4, 4, audioio_mixer_obj___exit__);
+
+
+//| .. method:: play(sample, *, voice=0, loop=False)
+//|
+//| Plays the sample once when loop=False and continuously when loop=True.
+//| Does not block. Use `playing` to block.
+//|
+//| Sample must be an `audioio.WaveFile`, `audioio.Mixer` or `audioio.RawSample`.
+//|
+//| The sample must match the Mixer's encoding settings given in the constructor.
+//|
+STATIC mp_obj_t audioio_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_sample, ARG_voice, ARG_loop };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED },
+ { MP_QSTR_voice, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
+ };
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_obj_t sample = args[ARG_sample].u_obj;
+ common_hal_audioio_mixer_play(self, sample, args[ARG_voice].u_int, args[ARG_loop].u_bool);
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_play_obj, 1, audioio_mixer_obj_play);
+
+//| .. method:: stop_voice(voice=0)
+//|
+//| Stops playback of the sample on the given voice.
+//|
+STATIC mp_obj_t audioio_mixer_obj_stop_voice(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_voice };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_voice, MP_ARG_INT, {.u_int = 0} },
+ };
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ common_hal_audioio_mixer_stop_voice(self, args[ARG_voice].u_int);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_stop_voice_obj, 1, audioio_mixer_obj_stop_voice);
+
+//| .. attribute:: playing
+//|
+//| True when any voice is being output. (read-only)
+//|
+STATIC mp_obj_t audioio_mixer_obj_get_playing(mp_obj_t self_in) {
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ return mp_obj_new_bool(common_hal_audioio_mixer_get_playing(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_playing_obj, audioio_mixer_obj_get_playing);
+
+const mp_obj_property_t audioio_mixer_playing_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audioio_mixer_get_playing_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: sample_rate
+//|
+//| 32 bit value that dictates how quickly samples are played in Hertz (cycles per second).
+//|
+STATIC mp_obj_t audioio_mixer_obj_get_sample_rate(mp_obj_t self_in) {
+ audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_audioio_mixer_deinited(self));
+ return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_mixer_get_sample_rate(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_sample_rate_obj, audioio_mixer_obj_get_sample_rate);
+
+
+const mp_obj_property_t audioio_mixer_sample_rate_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audioio_mixer_get_sample_rate_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t audioio_mixer_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_mixer_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_mixer___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audioio_mixer_play_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_voice), MP_ROM_PTR(&audioio_mixer_stop_voice_obj) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audioio_mixer_playing_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_mixer_sample_rate_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(audioio_mixer_locals_dict, audioio_mixer_locals_dict_table);
+
+const mp_obj_type_t audioio_mixer_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Mixer,
+ .make_new = audioio_mixer_make_new,
+ .locals_dict = (mp_obj_dict_t*)&audioio_mixer_locals_dict,
+};
diff --git a/shared-bindings/audioio/Mixer.h b/shared-bindings/audioio/Mixer.h
new file mode 100644
index 000000000..832072b8f
--- /dev/null
+++ b/shared-bindings/audioio/Mixer.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "shared-module/audioio/Mixer.h"
+#include "shared-bindings/audioio/RawSample.h"
+
+extern const mp_obj_type_t audioio_mixer_type;
+
+void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self,
+ uint8_t voice_count,
+ uint32_t buffer_size,
+ uint8_t bits_per_sample,
+ bool samples_signed,
+ uint8_t channel_count,
+ uint32_t sample_rate);
+
+void common_hal_audioio_mixer_deinit(audioio_mixer_obj_t* self);
+bool common_hal_audioio_mixer_deinited(audioio_mixer_obj_t* self);
+void common_hal_audioio_mixer_play(audioio_mixer_obj_t* self, mp_obj_t sample, uint8_t voice, bool loop);
+void common_hal_audioio_mixer_stop_voice(audioio_mixer_obj_t* self, uint8_t voice);
+
+bool common_hal_audioio_mixer_get_playing(audioio_mixer_obj_t* self);
+uint32_t common_hal_audioio_mixer_get_sample_rate(audioio_mixer_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H
diff --git a/shared-bindings/audioio/WaveFile.c b/shared-bindings/audioio/WaveFile.c
index 4ff0abdda..2d2ef578b 100644
--- a/shared-bindings/audioio/WaveFile.c
+++ b/shared-bindings/audioio/WaveFile.c
@@ -138,6 +138,43 @@ const mp_obj_property_t audioio_wavefile_sample_rate_obj = {
(mp_obj_t)&mp_const_none_obj},
};
+//| .. attribute:: bits_per_sample
+//|
+//| Bits per sample. (read only)
+//|
+STATIC mp_obj_t audioio_wavefile_obj_get_bits_per_sample(mp_obj_t self_in) {
+ audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_audioio_wavefile_deinited(self));
+ return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_bits_per_sample(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_bits_per_sample_obj, audioio_wavefile_obj_get_bits_per_sample);
+
+const mp_obj_property_t audioio_wavefile_bits_per_sample_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audioio_wavefile_get_bits_per_sample_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: channel_count
+//|
+//| Number of audio channels. (read only)
+//|
+STATIC mp_obj_t audioio_wavefile_obj_get_channel_count(mp_obj_t self_in) {
+ audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_audioio_wavefile_deinited(self));
+ return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_channel_count(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_channel_count_obj, audioio_wavefile_obj_get_channel_count);
+
+const mp_obj_property_t audioio_wavefile_channel_count_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&audioio_wavefile_get_channel_count_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
STATIC const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = {
// Methods
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_wavefile_deinit_obj) },
@@ -146,6 +183,8 @@ STATIC const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = {
// Properties
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_wavefile_sample_rate_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audioio_wavefile_bits_per_sample_obj) },
+ { MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audioio_wavefile_channel_count_obj) },
};
STATIC MP_DEFINE_CONST_DICT(audioio_wavefile_locals_dict, audioio_wavefile_locals_dict_table);
diff --git a/shared-bindings/audioio/WaveFile.h b/shared-bindings/audioio/WaveFile.h
index 255ffbcd5..62a4200dc 100644
--- a/shared-bindings/audioio/WaveFile.h
+++ b/shared-bindings/audioio/WaveFile.h
@@ -40,5 +40,7 @@ void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self);
bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self);
uint32_t common_hal_audioio_wavefile_get_sample_rate(audioio_wavefile_obj_t* self);
void common_hal_audioio_wavefile_set_sample_rate(audioio_wavefile_obj_t* self, uint32_t sample_rate);
+uint8_t common_hal_audioio_wavefile_get_bits_per_sample(audioio_wavefile_obj_t* self);
+uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t* self);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_WAVEFILE_H
diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c
index 8a00b43d8..4786b6425 100644
--- a/shared-bindings/audioio/__init__.c
+++ b/shared-bindings/audioio/__init__.c
@@ -32,6 +32,8 @@
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/audioio/__init__.h"
#include "shared-bindings/audioio/AudioOut.h"
+#include "shared-bindings/audioio/Mixer.h"
+#include "shared-bindings/audioio/RawSample.h"
#include "shared-bindings/audioio/WaveFile.h"
//| :mod:`audioio` --- Support for audio input and output
@@ -49,6 +51,7 @@
//| :maxdepth: 3
//|
//| AudioOut
+//| Mixer
//| RawSample
//| WaveFile
//|
@@ -61,6 +64,7 @@
STATIC const mp_rom_map_elem_t audioio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audioio) },
{ MP_ROM_QSTR(MP_QSTR_AudioOut), MP_ROM_PTR(&audioio_audioout_type) },
+ { MP_ROM_QSTR(MP_QSTR_Mixer), MP_ROM_PTR(&audioio_mixer_type) },
{ MP_ROM_QSTR(MP_QSTR_RawSample), MP_ROM_PTR(&audioio_rawsample_type) },
{ MP_ROM_QSTR(MP_QSTR_WaveFile), MP_ROM_PTR(&audioio_wavefile_type) },
};
diff --git a/shared-bindings/bleio/Adapter.c b/shared-bindings/bleio/Adapter.c
index bfe87071d..d9449d3ab 100644
--- a/shared-bindings/bleio/Adapter.c
+++ b/shared-bindings/bleio/Adapter.c
@@ -25,6 +25,7 @@
*/
#include "py/objproperty.h"
+#include "shared-bindings/bleio/Address.h"
#include "shared-bindings/bleio/Adapter.h"
//| .. currentmodule:: bleio
@@ -57,8 +58,6 @@
//| MAC address of the BLE adapter. (read-only)
//|
-#define BLE_ADDRESS_LEN 17
-
STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) {
return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled());
}
@@ -81,16 +80,12 @@ const mp_obj_property_t bleio_adapter_enabled_obj = {
};
STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) {
- vstr_t vstr;
- vstr_init(&vstr, BLE_ADDRESS_LEN);
-
- common_hal_bleio_adapter_get_address(&vstr);
-
- const mp_obj_t mac_str = mp_obj_new_str(vstr.buf, vstr.len);
+ mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, mp_const_none);
+ bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj);
- vstr_clear(&vstr);
+ common_hal_bleio_adapter_get_address(address);
- return mac_str;
+ return obj;
}
MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address);
diff --git a/shared-bindings/bleio/Adapter.h b/shared-bindings/bleio/Adapter.h
index 6c5d56948..fe3886e59 100644
--- a/shared-bindings/bleio/Adapter.h
+++ b/shared-bindings/bleio/Adapter.h
@@ -27,12 +27,12 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
-#include "py/obj.h"
+#include "shared-module/bleio/Address.h"
const mp_obj_type_t bleio_adapter_type;
extern bool common_hal_bleio_adapter_get_enabled(void);
extern void common_hal_bleio_adapter_set_enabled(bool enabled);
-extern void common_hal_bleio_adapter_get_address(vstr_t *address);
+extern void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H
diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c
new file mode 100644
index 000000000..ec23ff207
--- /dev/null
+++ b/shared-bindings/bleio/Address.c
@@ -0,0 +1,167 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "py/objproperty.h"
+#include "py/objstr.h"
+#include "py/runtime.h"
+#include "shared-bindings/bleio/Address.h"
+#include "shared-module/bleio/Address.h"
+
+#define ADDRESS_LONG_LEN 17 // XX:XX:XX:XX:XX:XX
+#define ADDRESS_SHORT_LEN 12 // XXXXXXXXXXXX
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`Address` -- BLE address
+//| =========================================================
+//|
+//| Encapsulates the address of a BLE device.
+//|
+
+//| .. class:: Address(address)
+//|
+//| Create a new Address object encapsulating the address value.
+//| The value itself can be one of:
+//|
+//| - a `str` value in the format of 'XXXXXXXXXXXX' or 'XX:XX:XX:XX:XX'
+//| - a `bytes` or `bytearray` containing 6 bytes
+//| - another Address object
+//|
+//| :param address: The address to encapsulate
+//|
+
+//| .. attribute:: type
+//|
+//| The address type. One of:
+//|
+//| - `bleio.AddressType.PUBLIC`
+//| - `bleio.AddressType.RANDOM_STATIC`
+//| - `bleio.AddressType.RANDOM_PRIVATE_RESOLVABLE`
+//| - `bleio.AddressType.RANDOM_PRIVATE_NON_RESOLVABLE`
+//|
+STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 1, 1, true);
+ bleio_address_obj_t *self = m_new_obj(bleio_address_obj_t);
+ self->base.type = &bleio_address_type;
+ self->type = ADDRESS_PUBLIC;
+
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+
+ enum { ARG_address };
+ static const mp_arg_t allowed_args[] = {
+ { ARG_address, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const mp_obj_t address = args[ARG_address].u_obj;
+
+ if (MP_OBJ_IS_STR(address)) {
+ GET_STR_DATA_LEN(address, str_data, str_len);
+ const bool is_long = (str_len == ADDRESS_LONG_LEN);
+ const bool is_short = (str_len == ADDRESS_SHORT_LEN);
+
+ if (is_long || is_short) {
+ size_t i = str_len - 1;
+ for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) {
+ self->value[b] = unichar_xdigit_value(str_data[i]) |
+ unichar_xdigit_value(str_data[i - 1]) << 4;
+
+ i -= is_long ? 3 : 2;
+ }
+ } else {
+ mp_raise_ValueError(translate("Wrong address length"));
+ }
+ } else if (MP_OBJ_IS_TYPE(address, &mp_type_bytearray) || MP_OBJ_IS_TYPE(address, &mp_type_bytes)) {
+ mp_buffer_info_t buf_info;
+ mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ);
+ if (buf_info.len != BLEIO_ADDRESS_BYTES) {
+ mp_raise_ValueError(translate("Wrong number of bytes provided"));
+ }
+
+ for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) {
+ self->value[BLEIO_ADDRESS_BYTES - b - 1] = ((uint8_t*)buf_info.buf)[b];
+ }
+ } else if (MP_OBJ_IS_TYPE(address, &bleio_address_type)) {
+ // deep copy
+ bleio_address_obj_t *other = MP_OBJ_TO_PTR(address);
+ self->type = other->type;
+ memcpy(self->value, other->value, BLEIO_ADDRESS_BYTES);
+ }
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_printf(print, "Address('"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT"')",
+ self->value[5], self->value[4], self->value[3],
+ self->value[2], self->value[1], self->value[0]);
+}
+
+STATIC mp_obj_t bleio_address_get_type(mp_obj_t self_in) {
+ bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (self->type == ADDRESS_PUBLIC) {
+ return (mp_obj_t)&bleio_addresstype_public_obj;
+ } else if (self->type == ADDRESS_RANDOM_STATIC) {
+ return (mp_obj_t)&bleio_addresstype_random_static_obj;
+ } else if (self->type == ADDRESS_RANDOM_PRIVATE_RESOLVABLE) {
+ return (mp_obj_t)&bleio_addresstype_random_private_resolvable_obj;
+ } else if (self->type == ADDRESS_RANDOM_PRIVATE_NON_RESOLVABLE) {
+ return (mp_obj_t)&bleio_addresstype_random_private_non_resolvable_obj;
+ }
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_address_get_type_obj, bleio_address_get_type);
+
+const mp_obj_property_t bleio_address_type_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&bleio_address_get_type_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_address_locals_dict, bleio_address_locals_dict_table);
+
+const mp_obj_type_t bleio_address_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Address,
+ .print = bleio_address_print,
+ .make_new = bleio_address_make_new,
+ .locals_dict = (mp_obj_dict_t*)&bleio_address_locals_dict
+};
diff --git a/shared-bindings/bleio/Address.h b/shared-bindings/bleio/Address.h
new file mode 100644
index 000000000..9c9e20968
--- /dev/null
+++ b/shared-bindings/bleio/Address.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H
+
+#include "py/objtype.h"
+
+extern const mp_obj_type_t bleio_address_type;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H
diff --git a/shared-bindings/bleio/AddressType.c b/shared-bindings/bleio/AddressType.c
new file mode 100644
index 000000000..cf2151c94
--- /dev/null
+++ b/shared-bindings/bleio/AddressType.c
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/bleio/AddressType.h"
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`AddressType` -- defines the type of a BLE address
+//| =============================================================
+//|
+//| .. class:: bleio.AddressType
+//|
+//| Enum-like class to define the type of a BLE address, see also `bleio.Address`.
+//|
+//| .. data:: PUBLIC
+//|
+//| The address is public
+//|
+//| .. data:: RANDOM_STATIC
+//|
+//| The address is random static
+//|
+//| .. data:: RANDOM_PRIVATE_RESOLVABLE
+//|
+//| The address is random private resolvable
+//|
+//| .. data:: RANDOM_PRIVATE_NON_RESOLVABLE
+//|
+//| The address is private non-resolvable
+//|
+const mp_obj_type_t bleio_addresstype_type;
+
+const bleio_addresstype_obj_t bleio_addresstype_public_obj = {
+ { &bleio_addresstype_type },
+};
+
+const bleio_addresstype_obj_t bleio_addresstype_random_static_obj = {
+ { &bleio_addresstype_type },
+};
+
+const bleio_addresstype_obj_t bleio_addresstype_random_private_resolvable_obj = {
+ { &bleio_addresstype_type },
+};
+
+const bleio_addresstype_obj_t bleio_addresstype_random_private_non_resolvable_obj = {
+ { &bleio_addresstype_type },
+};
+
+STATIC const mp_rom_map_elem_t bleio_addresstype_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_ROM_PTR(&bleio_addresstype_public_obj) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_ROM_PTR(&bleio_addresstype_random_static_obj) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_ROM_PTR(&bleio_addresstype_random_private_resolvable_obj) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_ROM_PTR(&bleio_addresstype_random_private_non_resolvable_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(bleio_addresstype_locals_dict, bleio_addresstype_locals_dict_table);
+
+STATIC void bleio_addresstype_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ qstr type = MP_QSTR_PUBLIC;
+
+ if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_static_obj)) {
+ type = MP_QSTR_RANDOM_STATIC;
+ } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_private_resolvable_obj)) {
+ type = MP_QSTR_RANDOM_PRIVATE_RESOLVABLE;
+ } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_private_non_resolvable_obj)) {
+ type = MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE;
+ }
+
+ mp_printf(print, "%q.%q.%q", MP_QSTR_bleio, MP_QSTR_AddressType, type);
+}
+
+const mp_obj_type_t bleio_addresstype_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_AddressType,
+ .print = bleio_addresstype_print,
+ .locals_dict = (mp_obj_t)&bleio_addresstype_locals_dict,
+};
diff --git a/shared-bindings/bleio/AddressType.h b/shared-bindings/bleio/AddressType.h
new file mode 100644
index 000000000..e69caffab
--- /dev/null
+++ b/shared-bindings/bleio/AddressType.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H
+
+#include "py/obj.h"
+
+typedef enum {
+ ADDRESS_PUBLIC,
+ ADDRESS_RANDOM_STATIC,
+ ADDRESS_RANDOM_PRIVATE_RESOLVABLE,
+ ADDRESS_RANDOM_PRIVATE_NON_RESOLVABLE
+} bleio_address_type_t;
+
+extern const mp_obj_type_t bleio_addresstype_type;
+
+typedef struct {
+ mp_obj_base_t base;
+} bleio_addresstype_obj_t;
+
+extern const bleio_addresstype_obj_t bleio_addresstype_public_obj;
+extern const bleio_addresstype_obj_t bleio_addresstype_random_static_obj;
+extern const bleio_addresstype_obj_t bleio_addresstype_random_private_resolvable_obj;
+extern const bleio_addresstype_obj_t bleio_addresstype_random_private_non_resolvable_obj;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H
diff --git a/shared-bindings/bleio/AdvertisementData.c b/shared-bindings/bleio/AdvertisementData.c
new file mode 100644
index 000000000..9cfdd74e9
--- /dev/null
+++ b/shared-bindings/bleio/AdvertisementData.c
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/obj.h"
+#include "shared-module/bleio/AdvertisementData.h"
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`AdvertisementData` -- data used during BLE advertising
+//| ==============================================================
+//|
+//| Represents the data to be broadcast during BLE advertising.
+//|
+
+STATIC const mp_rom_map_elem_t bleio_advertisementdata_locals_dict_table[] = {
+ // Static variables
+ { MP_ROM_QSTR(MP_QSTR_FLAGS), MP_ROM_INT(AdFlags) },
+ { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_16BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf16BitServiceClassUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_16BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf16BitServiceClassUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_32BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf32BitServiceClassUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_32BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf32BitServiceClassUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_128BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf128BitServiceClassUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_128BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf128BitServiceClassUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_SHORTENED_LOCAL_NAME), MP_ROM_INT(AdShortenedLocalName) },
+ { MP_ROM_QSTR(MP_QSTR_COMPLETE_LOCAL_NAME), MP_ROM_INT(AdCompleteLocalName) },
+ { MP_ROM_QSTR(MP_QSTR_TX_POWER_LEVEL), MP_ROM_INT(AdTxPowerLevel) },
+ { MP_ROM_QSTR(MP_QSTR_CLASS_OF_DEVICE), MP_ROM_INT(AdClassOfDevice) },
+ { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_HASH_C), MP_ROM_INT(AdSimplePairingHashC) },
+ { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_RANDOMIZER_R), MP_ROM_INT(AdSimplePairingRandomizerR) },
+ { MP_ROM_QSTR(MP_QSTR_SECURITY_MANAGER_TK_VALUE), MP_ROM_INT(AdSecurityManagerTKValue) },
+ { MP_ROM_QSTR(MP_QSTR_SECURITY_MANAGER_OOB_FLAGS), MP_ROM_INT(AdSecurityManagerOOBFlags) },
+ { MP_ROM_QSTR(MP_QSTR_SLAVE_CONNECTION_INTERVAL_RANGE), MP_ROM_INT(AdSlaveConnectionIntervalRange) },
+ { MP_ROM_QSTR(MP_QSTR_LIST_OF_16BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf16BitServiceSolicitationUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_LIST_OF_128BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf128BitServiceSolicitationUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA), MP_ROM_INT(AdServiceData) },
+ { MP_ROM_QSTR(MP_QSTR_PUBLIC_TARGET_ADDRESS), MP_ROM_INT(AdPublicTargetAddress) },
+ { MP_ROM_QSTR(MP_QSTR_RANDOM_TARGET_ADDRESS), MP_ROM_INT(AdRandomTargetAddress) },
+ { MP_ROM_QSTR(MP_QSTR_APPEARANCE), MP_ROM_INT(AdAppearance) },
+ { MP_ROM_QSTR(MP_QSTR_ADVERTISING_INTERNAL), MP_ROM_INT(AdAdvertisingInterval) },
+ { MP_ROM_QSTR(MP_QSTR_LE_BLUETOOTH_DEVICE_ADDRESS), MP_ROM_INT(AdLEBluetoothDeviceAddress) },
+ { MP_ROM_QSTR(MP_QSTR_LE_ROLE), MP_ROM_INT(AdLERole) },
+ { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_HASH_C256), MP_ROM_INT(AdSimplePairingHashC256) },
+ { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_RANDOMIZER_R256), MP_ROM_INT(AdSimplePairingRandomizerR256) },
+ { MP_ROM_QSTR(MP_QSTR_LIST_OF_32BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf32BitServiceSolicitationUUIDs) },
+ { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA_32BIT_UUID), MP_ROM_INT(AdServiceData32BitUUID) },
+ { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA_128BIT_UUID), MP_ROM_INT(AdServiceData128BitUUID) },
+ { MP_ROM_QSTR(MP_QSTR_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE), MP_ROM_INT(AdLESecureConnectionsConfirmationValue) },
+ { MP_ROM_QSTR(MP_QSTR_LE_SECURE_CONNECTIONS_RANDOM_VALUE), MP_ROM_INT(AdLESecureConnectionsRandomValue) },
+ { MP_ROM_QSTR(MP_QSTR_URI), MP_ROM_INT(AdURI) },
+ { MP_ROM_QSTR(MP_QSTR_INDOOR_POSITIONING), MP_ROM_INT(AdIndoorPositioning) },
+ { MP_ROM_QSTR(MP_QSTR_TRANSPORT_DISCOVERY_DATA), MP_ROM_INT(AdTransportDiscoveryData) },
+ { MP_ROM_QSTR(MP_QSTR_LE_SUPPORTED_FEATURES), MP_ROM_INT(AdLESupportedFeatures) },
+ { MP_ROM_QSTR(MP_QSTR_CHANNEL_MAP_UPDATE_INDICATION), MP_ROM_INT(AdChannelMapUpdateIndication) },
+ { MP_ROM_QSTR(MP_QSTR_PB_ADV), MP_ROM_INT(AdPBADV) },
+ { MP_ROM_QSTR(MP_QSTR_MESH_MESSAGE), MP_ROM_INT(AdMeshMessage) },
+ { MP_ROM_QSTR(MP_QSTR_MESH_BEACON), MP_ROM_INT(AdMeshBeacon) },
+ { MP_ROM_QSTR(MP_QSTR_3D_INFORMATION_DATA), MP_ROM_INT(Ad3DInformationData) },
+ { MP_ROM_QSTR(MP_QSTR_MANUFACTURER_SPECIFIC_DATA), MP_ROM_INT(AdManufacturerSpecificData) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_advertisementdata_locals_dict, bleio_advertisementdata_locals_dict_table);
+
+const mp_obj_type_t bleio_advertisementdata_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_AdvertisementData,
+ .locals_dict = (mp_obj_dict_t*)&bleio_advertisementdata_locals_dict
+};
diff --git a/shared-bindings/bleio/AdvertisementData.h b/shared-bindings/bleio/AdvertisementData.h
new file mode 100644
index 000000000..05b5a2c8d
--- /dev/null
+++ b/shared-bindings/bleio/AdvertisementData.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H
+
+#include "py/obj.h"
+
+extern const mp_obj_type_t bleio_advertisementdata_type;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H
diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c
new file mode 100644
index 000000000..369f3f991
--- /dev/null
+++ b/shared-bindings/bleio/Characteristic.c
@@ -0,0 +1,332 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/bleio/UUID.h"
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`Characteristic` -- BLE service characteristic
+//| =========================================================
+//|
+//| Stores information about a BLE service characteristic and allows to read
+//| and write the characteristic's value.
+//|
+
+//| .. class:: Characteristic(uuid)
+//|
+//| Create a new Characteristic object identified by the specified UUID.
+//|
+//| :param bleio.UUID uuid: The uuid of the characteristic
+//|
+
+//| .. attribute:: broadcast
+//|
+//| A `bool` specifying if the characteristic allows broadcasting its value.
+//|
+
+//| .. attribute:: indicate
+//|
+//| A `bool` specifying if the characteristic allows indicating its value.
+//|
+
+//| .. attribute:: notify
+//|
+//| A `bool` specifying if the characteristic allows notifying its value.
+//|
+
+//| .. attribute:: read
+//|
+//| A `bool` specifying if the characteristic allows reading its value.
+//|
+
+//| .. attribute:: uuid
+//|
+//| The UUID of this characteristic. (read-only)
+//|
+
+//| .. attribute:: value
+//|
+//| The value of this characteristic. The value can be written to if the `write` property allows it.
+//| If the `read` property allows it, the value can be read. If the `notify` property is set, writting
+//| to the value will generate a BLE notification.
+//|
+
+//| .. attribute:: write
+//|
+//| A `bool` specifying if the characteristic allows writting to its value.
+//|
+
+//| .. attribute:: write_no_resp
+//|
+//| A `bool` specifying if the characteristic allows writting to its value without response.
+//|
+STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_printf(print, "Characteristic(uuid: 0x"HEX2_FMT""HEX2_FMT" handle: 0x" HEX2_FMT ")",
+ self->uuid->value[1], self->uuid->value[0], self->handle);
+}
+
+STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 1, 1, true);
+ bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t);
+ self->base.type = &bleio_characteristic_type;
+ self->service = NULL;
+ self->value_data = NULL;
+
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+
+ enum { ARG_uuid };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_uuid, MP_ARG_REQUIRED| MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const mp_obj_t uuid = args[ARG_uuid].u_obj;
+
+ if (uuid == mp_const_none) {
+ return MP_OBJ_FROM_PTR(self);
+ }
+
+ if (MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) {
+ self->uuid = MP_OBJ_TO_PTR(uuid);
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ translate("Invalid UUID parameter")));
+ }
+
+ common_hal_bleio_characteristic_construct(self);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(self->props.broadcast);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast);
+
+STATIC mp_obj_t bleio_characteristic_set_broadcast(mp_obj_t self_in, mp_obj_t broadcast_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ self->props.broadcast = mp_obj_is_true(broadcast_in);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_broadcast_obj, bleio_characteristic_set_broadcast);
+
+const mp_obj_property_t bleio_characteristic_broadcast_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_broadcast_obj,
+ (mp_obj_t)&bleio_characteristic_set_broadcast_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(self->props.indicate);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_indicate_obj, bleio_characteristic_get_indicate);
+
+STATIC mp_obj_t bleio_characteristic_set_indicate(mp_obj_t self_in, mp_obj_t indicate_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ self->props.indicate = mp_obj_is_true(indicate_in);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_indicate_obj, bleio_characteristic_set_indicate);
+
+const mp_obj_property_t bleio_characteristic_indicate_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_indicate_obj,
+ (mp_obj_t)&bleio_characteristic_set_indicate_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(self->props.notify);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_notify_obj, bleio_characteristic_get_notify);
+
+STATIC mp_obj_t bleio_characteristic_set_notify(mp_obj_t self_in, mp_obj_t notify_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ self->props.notify = mp_obj_is_true(notify_in);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_notify_obj, bleio_characteristic_set_notify);
+
+const mp_obj_property_t bleio_characteristic_notify_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_notify_obj,
+ (mp_obj_t)&bleio_characteristic_set_notify_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(self->props.read);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_read_obj, bleio_characteristic_get_read);
+
+STATIC mp_obj_t bleio_characteristic_set_read(mp_obj_t self_in, mp_obj_t read_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ self->props.read = mp_obj_is_true(read_in);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_read_obj, bleio_characteristic_set_read);
+
+const mp_obj_property_t bleio_characteristic_read_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_read_obj,
+ (mp_obj_t)&bleio_characteristic_set_read_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(self->props.write);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_obj, bleio_characteristic_get_write);
+
+STATIC mp_obj_t bleio_characteristic_set_write(mp_obj_t self_in, mp_obj_t write_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ self->props.write = mp_obj_is_true(write_in);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_obj, bleio_characteristic_set_write);
+
+const mp_obj_property_t bleio_characteristic_write_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_write_obj,
+ (mp_obj_t)&bleio_characteristic_set_write_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_characteristic_get_write_wo_resp(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_bool(self->props.write_wo_resp);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_wo_resp_obj, bleio_characteristic_get_write_wo_resp);
+
+STATIC mp_obj_t bleio_characteristic_set_write_wo_resp(mp_obj_t self_in, mp_obj_t write_wo_resp_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ self->props.write_wo_resp = mp_obj_is_true(write_wo_resp_in);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_wo_resp_obj, bleio_characteristic_set_write_wo_resp);
+
+const mp_obj_property_t bleio_characteristic_write_wo_resp_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_write_wo_resp_obj,
+ (mp_obj_t)&bleio_characteristic_set_write_wo_resp_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return MP_OBJ_FROM_PTR(self->uuid);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_uuid_obj, bleio_characteristic_get_uuid);
+
+const mp_obj_property_t bleio_characteristic_uuid_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_uuid_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_bleio_characteristic_read_value(self);
+
+ return self->value_data;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_characteristic_get_value);
+
+STATIC mp_obj_t bleio_characteristic_set_value(mp_obj_t self_in, mp_obj_t value_in) {
+ bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ);
+
+ common_hal_bleio_characteristic_write_value(self, &bufinfo);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_value_obj, bleio_characteristic_set_value);
+
+const mp_obj_property_t bleio_characteristic_value_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_characteristic_get_value_obj,
+ (mp_obj_t)&bleio_characteristic_set_value_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_broadcast), MP_ROM_PTR(&bleio_characteristic_broadcast_obj) },
+ { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&bleio_characteristic_indicate_obj) },
+ { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&bleio_characteristic_notify_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&bleio_characteristic_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) },
+ { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_characteristic_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write_wo_resp), MP_ROM_PTR(&bleio_characteristic_write_wo_resp_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table);
+
+const mp_obj_type_t bleio_characteristic_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Characteristic,
+ .print = bleio_characteristic_print,
+ .make_new = bleio_characteristic_make_new,
+ .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict
+};
diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/bleio/Characteristic.h
new file mode 100644
index 000000000..0e99e97cc
--- /dev/null
+++ b/shared-bindings/bleio/Characteristic.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
+
+#include "shared-module/bleio/Characteristic.h"
+
+extern const mp_obj_type_t bleio_characteristic_type;
+
+extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self);
+extern void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self);
+extern void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H
diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c
new file mode 100644
index 000000000..df32a00e7
--- /dev/null
+++ b/shared-bindings/bleio/Descriptor.c
@@ -0,0 +1,171 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/bleio/Descriptor.h"
+#include "shared-bindings/bleio/UUID.h"
+
+enum {
+ DescriptorUuidCharacteristicExtendedProperties = 0x2900,
+ DescriptorUuidCharacteristicUserDescription = 0x2901,
+ DescriptorUuidClientCharacteristicConfiguration = 0x2902,
+ DescriptorUuidServerCharacteristicConfiguration = 0x2903,
+ DescriptorUuidCharacteristicPresentationFormat = 0x2904,
+ DescriptorUuidCharacteristicAggregateFormat = 0x2905,
+ DescriptorUuidValidRange = 0x2906,
+ DescriptorUuidExternalReportReference = 0x2907,
+ DescriptorUuidReportReference = 0x2908,
+ DescriptorUuidNumberOfDigitals = 0x2909,
+ DescriptorUuidValueTriggerSetting = 0x290A,
+ DescriptorUuidEnvironmentalSensingConfiguration = 0x290B,
+ DescriptorUuidEnvironmentalSensingMeasurement = 0x290C,
+ DescriptorUuidEnvironmentalSensingTriggerSetting = 0x290D,
+ DescriptorUuidTimeTriggerSetting = 0x290E,
+};
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`Descriptor` -- BLE descriptor
+//| =========================================================
+//|
+//| Stores information about a BLE descriptor.
+//| Descriptors are encapsulated by BLE characteristics and provide contextual
+//| information about the characteristic.
+//|
+
+//| .. class:: Descriptor(uuid)
+//|
+//| Create a new descriptor object with the UUID uuid.
+//| The value can be either of type `bleio.UUID` or any value allowed by the `bleio.UUID` constructor.
+
+//| .. attribute:: handle
+//|
+//| The descriptor handle. (read-only)
+//|
+
+//| .. attribute:: uuid
+//|
+//| The descriptor uuid. (read-only)
+//|
+STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 0, 1, true);
+ bleio_descriptor_obj_t *self = m_new_obj(bleio_descriptor_obj_t);
+ self->base.type = type;
+
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+
+ enum { ARG_uuid };
+ static const mp_arg_t allowed_args[] = {
+ { ARG_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const mp_obj_t uuid_arg = args[ARG_uuid].u_obj;
+
+ bleio_uuid_obj_t *uuid;
+ if (MP_OBJ_IS_TYPE(uuid_arg, &bleio_uuid_type)) {
+ uuid = MP_OBJ_TO_PTR(uuid_arg);
+ } else {
+ uuid = MP_OBJ_TO_PTR(bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid_arg));
+ }
+
+ common_hal_bleio_descriptor_construct(self, uuid);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC void bleio_descriptor_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_bleio_descriptor_print(self, print);
+}
+
+STATIC mp_obj_t bleio_descriptor_get_handle(mp_obj_t self_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_int(common_hal_bleio_descriptor_get_handle(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_handle_obj, bleio_descriptor_get_handle);
+
+const mp_obj_property_t bleio_descriptor_handle_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&bleio_descriptor_get_handle_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) {
+ bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ const mp_obj_t uuid = mp_obj_new_int(common_hal_bleio_descriptor_get_uuid(self));
+
+ return bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_uuid_obj, bleio_descriptor_get_uuid);
+
+const mp_obj_property_t bleio_descriptor_uuid_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&bleio_descriptor_get_uuid_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = {
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_handle), MP_ROM_PTR(&bleio_descriptor_handle_obj) },
+ { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) },
+
+ // Static variables
+ { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_EXTENDED_PROPERTIES), MP_ROM_INT(DescriptorUuidCharacteristicExtendedProperties) },
+ { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_USER_DESCRIPTION), MP_ROM_INT(DescriptorUuidCharacteristicUserDescription) },
+ { MP_ROM_QSTR(MP_QSTR_CLIENT_CHARACTERISTIC_CONFIGURATION), MP_ROM_INT(DescriptorUuidClientCharacteristicConfiguration) },
+ { MP_ROM_QSTR(MP_QSTR_SERVER_CHARACTERISTIC_CONFIGURATION), MP_ROM_INT(DescriptorUuidServerCharacteristicConfiguration) },
+ { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_PRESENTATION_FORMAT), MP_ROM_INT(DescriptorUuidCharacteristicPresentationFormat) },
+ { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_AGGREGATE_FORMAT), MP_ROM_INT(DescriptorUuidCharacteristicAggregateFormat) },
+ { MP_ROM_QSTR(MP_QSTR_VALID_RANGE), MP_ROM_INT(DescriptorUuidValidRange) },
+ { MP_ROM_QSTR(MP_QSTR_EXTERNAL_REPORT_REFERENCE), MP_ROM_INT(DescriptorUuidExternalReportReference) },
+ { MP_ROM_QSTR(MP_QSTR_REPORT_REFERENCE), MP_ROM_INT(DescriptorUuidReportReference) },
+ { MP_ROM_QSTR(MP_QSTR_NUMBER_OF_DIGITALS), MP_ROM_INT(DescriptorUuidNumberOfDigitals) },
+ { MP_ROM_QSTR(MP_QSTR_VALUE_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidValueTriggerSetting) },
+ { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_CONFIGURATION), MP_ROM_INT(DescriptorUuidEnvironmentalSensingConfiguration) },
+ { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_MEASUREMENT ), MP_ROM_INT(DescriptorUuidEnvironmentalSensingMeasurement) },
+ { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidEnvironmentalSensingTriggerSetting) },
+ { MP_ROM_QSTR(MP_QSTR_TIME_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidTimeTriggerSetting) }
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_descriptor_locals_dict, bleio_descriptor_locals_dict_table);
+
+const mp_obj_type_t bleio_descriptor_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Descriptor,
+ .print = bleio_descriptor_print,
+ .make_new = bleio_descriptor_make_new,
+ .locals_dict = (mp_obj_dict_t*)&bleio_descriptor_locals_dict
+};
diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/bleio/Descriptor.h
new file mode 100644
index 000000000..85310d304
--- /dev/null
+++ b/shared-bindings/bleio/Descriptor.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
+
+#include "common-hal/bleio/Descriptor.h"
+#include "common-hal/bleio/UUID.h"
+
+extern const mp_obj_type_t bleio_descriptor_type;
+
+extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid);
+extern void common_hal_bleio_descriptor_print(bleio_descriptor_obj_t *self, const mp_print_t *print);
+extern mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self);
+extern mp_int_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H
diff --git a/shared-bindings/bleio/Device.c b/shared-bindings/bleio/Device.c
new file mode 100644
index 000000000..94834ef7c
--- /dev/null
+++ b/shared-bindings/bleio/Device.c
@@ -0,0 +1,357 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "ble_drv.h"
+#include "py/objarray.h"
+#include "py/objproperty.h"
+#include "py/objstr.h"
+#include "py/runtime.h"
+#include "shared-bindings/bleio/Adapter.h"
+#include "shared-bindings/bleio/AddressType.h"
+#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/bleio/Device.h"
+#include "shared-bindings/bleio/Service.h"
+#include "shared-bindings/bleio/UUID.h"
+#include "shared-module/bleio/AdvertisementData.h"
+#include "shared-module/bleio/Device.h"
+#include "shared-module/bleio/ScanEntry.h"
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`Device` -- BLE device
+//| =========================================================
+//|
+//| Provides access a to BLE device, either in a Peripheral or Central role.
+//| When a device is created without any parameter passed to the constructor,
+//| it will be set to the Peripheral role. If a address is passed, the device
+//| will be a Central. For a Peripheral you can set the `name`, add services
+//| via `add_service` and then start and stop advertising via `start_advertising`
+//| and `stop_advertising`. For the Central, you can `bleio.Device.connect` and `bleio.Device.disconnect`
+//| to the device, once a connection is established, the device's services can
+//| be accessed using `services`.
+//|
+//| Usage::
+//|
+//| import bleio
+//|
+//| # Peripheral
+//| periph = bleio.Device()
+//|
+//| serv = bleio.Service(bleio.UUID(0x180f))
+//| p.add_service(serv)
+//|
+//| chara = bleio.Characteristic(bleio.UUID(0x2919))
+//| chara.read = True
+//| chara.notify = True
+//| serv.add_characteristic(chara)
+//|
+//| periph.start_advertising()
+//|
+//| # Central
+//| scanner = bleio.Scanner()
+//| entries = scanner.scan(2500)
+//|
+//| my_entry = None
+//| for entry in entries:
+//| if entry.name is not None and entry.name == 'MyDevice':
+//| my_entry = entry
+//| break
+//|
+//| central = bleio.Device(my_entry.address)
+//| central.connect()
+//|
+
+//| .. class:: Device(address=None, scan_entry=None)
+//|
+//| Create a new Device object. If the `address` or :py:data:`scan_entry` parameters are not `None`,
+//| the role is set to Central, otherwise it's set to Peripheral.
+//|
+//| :param bleio.Address address: The address of the device to connect to
+//| :param bleio.ScanEntry scan_entry: The scan entry returned from `bleio.Scanner`
+//|
+
+//| .. attribute:: name
+//|
+//| For the Peripheral role, this property can be used to read and write the device's name.
+//| For the Central role, this property will equal the name of the remote device, if one was
+//| advertised by the device. In the Central role this property is read-only.
+//|
+
+//| .. attribute:: services
+//|
+//| A `list` of `bleio.Service` that are offered by this device. (read-only)
+//| For a Peripheral device, this list will contain services added using `add_service`,
+//| for a Central, this list will be empty until a connection is established, at which point
+//| it will be filled with the remote device's services.
+//|
+
+//| .. method:: add_service(service)
+//|
+//| Appends the :py:data:`service` to the list of this devices's services.
+//| This method can only be called for Peripheral devices.
+//|
+//| :param bleio.Service service: the service to append
+//|
+
+//| .. method:: connect()
+//|
+//| Attempts a connection to the remote device. If the connection is successful,
+//| the device's services are available via `services`.
+//| This method can only be called for Central devices.
+//|
+
+//| .. method:: disconnect()
+//|
+//| Disconnects from the remote device.
+//| This method can only be called for Central devices.
+//|
+
+//| .. method:: start_advertising(connectable=True)
+//|
+//| Starts advertising the device. The device's name and
+//| services are put into the advertisement packets.
+//| If :py:data:`connectable` is `True` then other devices are allowed to conncet to this device.
+//| This method can only be called for Peripheral devices.
+//|
+
+//| .. method:: stop_advertising()
+//|
+//| Disconnects from the remote device.
+//| This method can only be called for Peripheral devices.
+//|
+
+// TODO: Add unique MAC address part to name
+static const char default_name[] = "CIRCUITPY";
+
+STATIC void bleio_device_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_printf(print, "Device(role: %s)", self->is_peripheral ? "Peripheral" : "Central");
+}
+
+STATIC mp_obj_t bleio_device_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 0, 1, true);
+ bleio_device_obj_t *self = m_new_obj(bleio_device_obj_t);
+ self->base.type = &bleio_device_type;
+ self->service_list = mp_obj_new_list(0, NULL);
+ self->notif_handler = mp_const_none;
+ self->conn_handler = mp_const_none;
+ self->conn_handle = 0xFFFF;
+ self->is_peripheral = true;
+
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+
+ enum { ARG_address, ARG_scan_entry };
+ static const mp_arg_t allowed_args[] = {
+ { ARG_address, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_scan_entry, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const mp_obj_t address_obj = args[ARG_address].u_obj;
+ const mp_obj_t scan_entry_obj = args[ARG_scan_entry].u_obj;
+
+ if (address_obj != mp_const_none) {
+ bleio_address_obj_t *address = MP_OBJ_TO_PTR(address_obj);
+
+ self->is_peripheral = false;
+ self->address.type = address->type;
+ memcpy(self->address.value, address->value, BLEIO_ADDRESS_BYTES);
+ } else if (scan_entry_obj != mp_const_none) {
+ bleio_scanentry_obj_t *scan_entry = MP_OBJ_TO_PTR(scan_entry_obj);
+
+ self->is_peripheral = false;
+ self->address.type = scan_entry->address.type;
+ memcpy(self->address.value, scan_entry->address.value, BLEIO_ADDRESS_BYTES);
+ } else {
+ self->name = mp_obj_new_str(default_name, strlen(default_name));
+ common_hal_bleio_adapter_get_address(&self->address);
+ }
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t bleio_device_add_service(mp_obj_t self_in, mp_obj_t service_in) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_in);
+
+ if (!self->is_peripheral) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ translate("Can't add services in Central mode")));
+ }
+
+ service->device = self;
+
+ mp_obj_list_append(self->service_list, service);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_device_add_service_obj, bleio_device_add_service);
+
+STATIC mp_obj_t bleio_device_connect(mp_obj_t self_in) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (self->is_peripheral) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ translate("Can't connect in Peripheral mode")));
+ }
+
+ common_hal_bleio_device_connect(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_connect_obj, bleio_device_connect);
+
+STATIC mp_obj_t bleio_device_disconnect(mp_obj_t self_in) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_bleio_device_disconnect(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_disconnect_obj, bleio_device_disconnect);
+
+STATIC mp_obj_t bleio_device_get_name(mp_obj_t self_in) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return self->name;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_get_name_obj, bleio_device_get_name);
+
+static mp_obj_t bleio_device_set_name(mp_obj_t self_in, mp_obj_t value) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (!self->is_peripheral) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ translate("Can't change the name in Central mode")));
+ }
+
+ self->name = value;
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_device_set_name_obj, bleio_device_set_name);
+
+const mp_obj_property_t bleio_device_name_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_device_get_name_obj,
+ (mp_obj_t)&bleio_device_set_name_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_device_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+
+ if (!self->is_peripheral) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ translate("Can't advertise in Central mode")));
+ }
+
+ enum { ARG_connectable, ARG_data };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ { MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_buffer_info_t bufinfo = { 0 };
+ if (args[ARG_data].u_obj != mp_const_none) {
+ mp_get_buffer_raise(args[ARG_data].u_obj, &bufinfo, MP_BUFFER_READ);
+ }
+
+ const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list);
+ for (size_t i = 0; i < service_list->len; ++i) {
+ bleio_service_obj_t *service = service_list->items[i];
+ if (service->handle == 0xFFFF) {
+ common_hal_bleio_device_add_service(self, service);
+ }
+ }
+
+ common_hal_bleio_device_start_advertising(self, args[ARG_connectable].u_bool, &bufinfo);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_device_start_advertising_obj, 0, bleio_device_start_advertising);
+
+STATIC mp_obj_t bleio_device_stop_advertising(mp_obj_t self_in) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (!self->is_peripheral) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ translate("Can't advertise in Central mode")));
+ }
+
+ common_hal_bleio_device_stop_advertising(self);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_stop_advertising_obj, bleio_device_stop_advertising);
+
+STATIC mp_obj_t bleio_device_get_services(mp_obj_t self_in) {
+ bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return self->service_list;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_get_services_obj, bleio_device_get_services);
+
+const mp_obj_property_t bleio_device_services_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_device_get_services_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC const mp_rom_map_elem_t bleio_device_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_add_service), MP_ROM_PTR(&bleio_device_add_service_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_device_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_device_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_device_start_advertising_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_device_stop_advertising_obj) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_device_name_obj) },
+ { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_device_services_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_device_locals_dict, bleio_device_locals_dict_table);
+
+const mp_obj_type_t bleio_device_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Device,
+ .print = bleio_device_print,
+ .make_new = bleio_device_make_new,
+ .locals_dict = (mp_obj_dict_t*)&bleio_device_locals_dict
+};
diff --git a/shared-bindings/bleio/Device.h b/shared-bindings/bleio/Device.h
new file mode 100644
index 000000000..aebf1d639
--- /dev/null
+++ b/shared-bindings/bleio/Device.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H
+
+#include "shared-module/bleio/AdvertisementData.h"
+#include "shared-module/bleio/Device.h"
+#include "shared-module/bleio/Service.h"
+
+extern const mp_obj_type_t bleio_device_type;
+
+extern void common_hal_bleio_device_add_service(bleio_device_obj_t *device, bleio_service_obj_t *service);
+extern void common_hal_bleio_device_start_advertising(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data);
+extern void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device);
+extern void common_hal_bleio_device_connect(bleio_device_obj_t *device);
+extern void common_hal_bleio_device_disconnect(bleio_device_obj_t *device);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H
diff --git a/shared-bindings/bleio/ScanEntry.c b/shared-bindings/bleio/ScanEntry.c
new file mode 100644
index 000000000..e452c7267
--- /dev/null
+++ b/shared-bindings/bleio/ScanEntry.c
@@ -0,0 +1,308 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "py/objarray.h"
+#include "py/objproperty.h"
+#include "py/objstr.h"
+#include "py/objtuple.h"
+#include "shared-bindings/bleio/Address.h"
+#include "shared-bindings/bleio/ScanEntry.h"
+#include "shared-bindings/bleio/UUID.h"
+#include "shared-module/bleio/AdvertisementData.h"
+#include "shared-module/bleio/ScanEntry.h"
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`ScanEntry` -- BLE scan response entry
+//| =========================================================
+//|
+//| Encapsulates information about a device that was received as a
+//| response to a BLE scan request.
+//|
+
+//| .. attribute:: address
+//|
+//| The address of the device. (read-only)
+//| This attribute is of type `bleio.Address`.
+//|
+
+//| .. attribute:: manufacturer_specific_data
+//|
+//| The manufacturer-specific data present in the advertisement packet. (read-only)
+//|
+
+//| .. attribute:: name
+//|
+//| The name of the device. (read-only)
+//| This attribute might be `None` if the data was missing from the advertisement packet.
+//|
+
+//| .. attribute:: raw_data
+//|
+//| All the advertisement data present in the packet. (read-only)
+//|
+
+//| .. attribute:: rssi
+//|
+//| The signal strength of the device at the time of the scan. (read-only)
+//|
+
+//| .. attribute:: service_uuids
+//|
+//| The address of the device. (read-only)
+//| This attribute is a list of `bleio.UUID`.
+//| This attribute might be empty or incomplete, depending on the advertisement packet.
+//| Currently only 16-bit UUIDS are listed.
+//|
+
+//| .. attribute:: tx_power_level
+//|
+//| The transmit power level of the device. (read-only)
+//| This attribute might be `None` if the data was missing from the advertisement packet.
+//|
+static uint8_t find_data_item(mp_obj_array_t *data_in, uint8_t type, uint8_t **data_out) {
+ uint16_t i = 0;
+ while (i < data_in->len) {
+ const uint8_t item_len = ((uint8_t*)data_in->items)[i];
+ const uint8_t item_type = ((uint8_t*)data_in->items)[i + 1];
+ if (item_type != type) {
+ i += (item_len + 1);
+ continue;
+ }
+
+ *data_out = &((uint8_t*)data_in->items)[i + 2];
+
+ return item_len;
+ }
+
+ return 0;
+}
+
+STATIC mp_obj_t scanentry_get_name(mp_obj_t self_in);
+
+STATIC void bleio_scanentry_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_scanentry_obj_t *self = (bleio_scanentry_obj_t *)self_in;
+ mp_printf(print, "ScanEntry(address: "HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT"",
+ self->address.value[5], self->address.value[4], self->address.value[3],
+ self->address.value[1], self->address.value[1], self->address.value[0]);
+
+ const mp_obj_t name_obj = scanentry_get_name(self_in);
+ if (name_obj != mp_const_none) {
+ mp_obj_str_t *str = MP_OBJ_TO_PTR(name_obj);
+ mp_printf(print, " name: %s", str->data);
+ }
+
+ mp_print_str(print, ")");
+}
+
+STATIC mp_obj_t bleio_scanentry_get_address(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, (mp_obj_t)&mp_const_none_obj);
+ bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj);
+
+ address->type = self->address.type;
+ memcpy(address->value, self->address.value, BLEIO_ADDRESS_BYTES);
+
+ return obj;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_address_obj, bleio_scanentry_get_address);
+
+const mp_obj_property_t bleio_scanentry_address_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bluepy_scanentry_get_address_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t scanentry_get_manufacturer_specific_data(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
+ uint8_t *manuf_data;
+
+ const uint8_t manuf_data_len = find_data_item(data, AdManufacturerSpecificData, &manuf_data);
+ if (manuf_data_len == 0) {
+ return mp_const_none;
+ }
+
+ return mp_obj_new_bytearray_by_ref(manuf_data_len, manuf_data);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_manufacturer_specific_data_obj, scanentry_get_manufacturer_specific_data);
+
+const mp_obj_property_t bleio_scanentry_manufacturer_specific_data_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&scanentry_get_manufacturer_specific_data_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t scanentry_get_name(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
+ uint8_t *name;
+
+ // Try for Complete but settle for Shortened
+ uint8_t name_len = find_data_item(data, AdCompleteLocalName, &name);
+ if (name_len == 0) {
+ name_len = find_data_item(data, AdShortenedLocalName, &name);
+ }
+
+ if (name_len == 0) {
+ return mp_const_none;
+ }
+
+ return mp_obj_new_str((const char*)name, name_len - 1);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_name_obj, scanentry_get_name);
+
+const mp_obj_property_t bleio_scanentry_name_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bluepy_scanentry_get_name_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t scanentry_get_raw_data(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_obj_t entries = mp_obj_new_list(0, NULL);
+
+ mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
+
+ uint16_t i = 0;
+ while (i < data->len) {
+ mp_obj_tuple_t *entry = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
+
+ const uint8_t item_len = ((uint8_t*)data->items)[i];
+ const uint8_t item_type = ((uint8_t*)data->items)[i + 1];
+
+ entry->items[0] = MP_OBJ_NEW_SMALL_INT(item_type);
+ entry->items[1] = mp_obj_new_bytearray(item_len - 1, &((uint8_t*)data->items)[i + 2]);
+ mp_obj_list_append(entries, MP_OBJ_FROM_PTR(entry));
+
+ i += (item_len + 1);
+ }
+
+ return entries;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_raw_data_obj, scanentry_get_raw_data);
+
+const mp_obj_property_t bleio_scanentry_raw_data_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_scanentry_get_raw_data_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t scanentry_get_rssi(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_int(self->rssi);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_rssi_obj, scanentry_get_rssi);
+
+const mp_obj_property_t bleio_scanentry_rssi_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bluepy_scanentry_get_rssi_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t scanentry_get_service_uuids(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
+ uint8_t *uuids;
+
+ // Try for Complete but settle for Incomplete
+ uint8_t uuids_len = find_data_item(data, AdCompleteListOf16BitServiceClassUUIDs, &uuids);
+ if (uuids_len == 0) {
+ uuids_len = find_data_item(data, AdIncompleteListOf16BitServiceClassUUIDs, &uuids);
+ }
+
+ mp_obj_t entries = mp_obj_new_list(0, NULL);
+ for (size_t i = 0; i < uuids_len / sizeof(uint16_t); ++i) {
+ const mp_obj_t uuid_int = mp_obj_new_int(uuids[sizeof(uint16_t) * i] | (uuids[sizeof(uint16_t) * i + 1] << 8));
+ const mp_obj_t uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid_int);
+
+ mp_obj_list_append(entries, uuid_obj);
+ }
+
+ // TODO: 32-bit UUIDs
+ // TODO: 128-bit UUIDs
+
+ return entries;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_service_uuids_obj, scanentry_get_service_uuids);
+
+const mp_obj_property_t bleio_scanentry_service_uuids_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&scanentry_get_service_uuids_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t scanentry_get_tx_power_level(mp_obj_t self_in) {
+ bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data);
+ uint8_t *tx_power;
+
+ const uint8_t tx_power_len = find_data_item(data, AdTxPowerLevel, &tx_power);
+ if (tx_power_len == 0) {
+ return mp_const_none;
+ }
+
+ return mp_obj_new_int((int8_t)(*tx_power));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_tx_power_level_obj, scanentry_get_tx_power_level);
+
+const mp_obj_property_t bleio_scanentry_tx_power_level_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&scanentry_get_tx_power_level_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC const mp_rom_map_elem_t bleio_scanentry_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_scanentry_address_obj) },
+ { MP_ROM_QSTR(MP_QSTR_manufacturer_specific_data), MP_ROM_PTR(&bleio_scanentry_manufacturer_specific_data_obj) },
+ { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_scanentry_name_obj) },
+ { MP_ROM_QSTR(MP_QSTR_raw_data), MP_ROM_PTR(&bleio_scanentry_raw_data_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bleio_scanentry_rssi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_service_uuids), MP_ROM_PTR(&bleio_scanentry_service_uuids_obj) },
+ { MP_ROM_QSTR(MP_QSTR_tx_power_level), MP_ROM_PTR(&bleio_scanentry_tx_power_level_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_dict_table);
+
+const mp_obj_type_t bleio_scanentry_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_ScanEntry,
+ .print = bleio_scanentry_print,
+ .locals_dict = (mp_obj_dict_t*)&bleio_scanentry_locals_dict
+};
diff --git a/shared-bindings/bleio/ScanEntry.h b/shared-bindings/bleio/ScanEntry.h
new file mode 100644
index 000000000..2b44ba3f4
--- /dev/null
+++ b/shared-bindings/bleio/ScanEntry.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H
+
+#include "py/obj.h"
+
+extern const mp_obj_type_t bleio_scanentry_type;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H
diff --git a/shared-bindings/bleio/Scanner.c b/shared-bindings/bleio/Scanner.c
new file mode 100644
index 000000000..5d19778f6
--- /dev/null
+++ b/shared-bindings/bleio/Scanner.c
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "shared-bindings/bleio/ScanEntry.h"
+#include "shared-bindings/bleio/Scanner.h"
+
+#define DEFAULT_INTERVAL 100
+#define DEFAULT_WINDOW 100
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`Scanner` -- scan for nearby BLE devices
+//| =========================================================
+//|
+//| Allows scanning for nearby BLE devices.
+//|
+//| Usage::
+//|
+//| import bleio
+//| scanner = bleio.Scanner()
+//| entries = scanner.scan(2500)
+//| print(entries)
+//|
+
+//| .. class:: Scanner()
+//|
+//| Create a new Scanner object.
+//|
+
+//| .. attribute:: interval
+//|
+//| The interval (in ms) between the start of two consecutive scan windows.
+//| Allowed values are between 10ms and 10.24 sec.
+//|
+
+//| .. attribute:: window
+//|
+//| The duration (in ms) in which a single BLE channel is scanned.
+//| Allowed values are between 10ms and 10.24 sec.
+//|
+
+//| .. method:: scan(timeout)
+//|
+//| Performs a BLE scan.
+//|
+//| :param int timeout: the scan timeout in ms
+//| :returns: advertising packets found
+//| :rtype: list of :py:class:`bleio.ScanEntry`
+//|
+STATIC void bleio_scanner_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_printf(print, "Scanner(interval: %d window: %d)", self->interval, self->window);
+}
+
+STATIC mp_obj_t bleio_scanner_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+ bleio_scanner_obj_t *self = m_new_obj(bleio_scanner_obj_t);
+ self->base.type = type;
+
+ self->interval = DEFAULT_INTERVAL;
+ self->window = DEFAULT_WINDOW;
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t bleio_scanner_get_interval(mp_obj_t self_in) {
+ bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_int(self->interval);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanner_get_interval_obj, bleio_scanner_get_interval);
+
+static mp_obj_t bleio_scanner_set_interval(mp_obj_t self_in, mp_obj_t value) {
+ bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ self->interval = mp_obj_get_int(value);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_set_interval_obj, bleio_scanner_set_interval);
+
+const mp_obj_property_t bleio_scanner_interval_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_scanner_get_interval_obj,
+ (mp_obj_t)&bleio_scanner_set_interval_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t scanner_scan(mp_obj_t self_in, mp_obj_t timeout_in) {
+ bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ const mp_int_t timeout = mp_obj_get_int(timeout_in);
+
+ self->adv_reports = mp_obj_new_list(0, NULL);
+
+ common_hal_bleio_scanner_scan(self, timeout);
+
+ return self->adv_reports;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_scan_obj, scanner_scan);
+
+STATIC mp_obj_t bleio_scanner_get_window(mp_obj_t self_in) {
+ bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return mp_obj_new_int(self->window);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanner_get_window_obj, bleio_scanner_get_window);
+
+static mp_obj_t bleio_scanner_set_window(mp_obj_t self_in, mp_obj_t value) {
+ bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ self->window = mp_obj_get_int(value);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_set_window_obj, bleio_scanner_set_window);
+
+const mp_obj_property_t bleio_scanner_window_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_scanner_get_window_obj,
+ (mp_obj_t)&bleio_scanner_set_window_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC const mp_rom_map_elem_t bleio_scanner_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_interval), MP_ROM_PTR(&bleio_scanner_interval_obj) },
+ { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bleio_scanner_scan_obj) },
+ { MP_ROM_QSTR(MP_QSTR_window), MP_ROM_PTR(&bleio_scanner_window_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_scanner_locals_dict, bleio_scanner_locals_dict_table);
+
+const mp_obj_type_t bleio_scanner_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Scanner,
+ .print = bleio_scanner_print,
+ .make_new = bleio_scanner_make_new,
+ .locals_dict = (mp_obj_dict_t*)&bleio_scanner_locals_dict
+};
diff --git a/shared-bindings/bleio/Scanner.h b/shared-bindings/bleio/Scanner.h
new file mode 100644
index 000000000..9bd071747
--- /dev/null
+++ b/shared-bindings/bleio/Scanner.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H
+
+#include "py/objtype.h"
+#include "shared-module/bleio/Scanner.h"
+
+extern const mp_obj_type_t bleio_scanner_type;
+
+extern void common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_int_t timeout);
+extern void common_hal_bleio_scanner_stop(bleio_scanner_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H
diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c
new file mode 100644
index 000000000..2d09cbc3c
--- /dev/null
+++ b/shared-bindings/bleio/Service.c
@@ -0,0 +1,170 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/bleio/Service.h"
+#include "shared-bindings/bleio/UUID.h"
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`Service` -- BLE service
+//| =========================================================
+//|
+//| Stores information about a BLE service and its characteristics.
+//|
+
+//| .. class:: Service(uuid, secondary=False)
+//|
+//| Create a new Service object identified by the specified UUID.
+//| To mark the service as secondary, pass `True` as :py:data:`secondary`.
+//|
+//| :param bleio.UUID uuid: The uuid of the service
+//| :param bool secondary: If the service is a secondary one
+//|
+
+//| .. method:: add_characteristic(characteristic)
+//|
+//| Appends the :py:data:`characteristic` to the list of this service's characteristics.
+//|
+//| :param bleio.Characteristic characteristic: the characteristic to append
+//|
+
+//| .. attribute:: characteristics
+//|
+//| A `list` of `bleio.Characteristic` that are offered by this service. (read-only)
+//|
+
+//| .. attribute:: uuid
+//|
+//| The UUID of this service. (read-only)
+//|
+STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ mp_printf(print, "Service(uuid: 0x"HEX2_FMT""HEX2_FMT")",
+ self->uuid->value[1], self->uuid->value[0]);
+}
+
+STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 1, 1, true);
+ bleio_service_obj_t *self = m_new_obj(bleio_service_obj_t);
+ self->base.type = &bleio_service_type;
+ self->device = NULL;
+ self->char_list = mp_obj_new_list(0, NULL);
+ self->handle = 0xFFFF;
+
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+
+ enum { ARG_uuid, ARG_secondary };
+ static const mp_arg_t allowed_args[] = {
+ { ARG_uuid, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ self->is_secondary = args[ARG_secondary].u_bool;
+
+ const mp_obj_t uuid = args[ARG_uuid].u_obj;
+
+ if (uuid == mp_const_none) {
+ return MP_OBJ_FROM_PTR(self);
+ }
+
+ if (MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) {
+ self->uuid = MP_OBJ_TO_PTR(uuid);
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ translate("Invalid UUID parameter")));
+ }
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t bleio_service_add_characteristic(mp_obj_t self_in, mp_obj_t characteristic_in) {
+ bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(characteristic_in);
+
+ if (self->uuid->type == UUID_TYPE_128BIT) {
+ characteristic->uuid->type = UUID_TYPE_128BIT;
+ characteristic->uuid->uuid_vs_idx = self->uuid->uuid_vs_idx;
+ }
+
+ characteristic->service = self;
+
+ mp_obj_list_append(self->char_list, characteristic);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_service_add_characteristic_obj, bleio_service_add_characteristic);
+
+STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) {
+ bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return self->char_list;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_characteristics_obj, bleio_service_get_characteristics);
+
+const mp_obj_property_t bleio_service_characteristics_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_service_get_characteristics_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) {
+ bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return MP_OBJ_FROM_PTR(self->uuid);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_uuid_obj, bleio_service_get_uuid);
+
+const mp_obj_property_t bleio_service_uuid_obj = {
+ .base.type = &mp_type_property,
+ .proxy = { (mp_obj_t)&bleio_service_get_uuid_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj },
+};
+
+STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_add_characteristic), MP_ROM_PTR(&bleio_service_add_characteristic_obj) },
+ { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) },
+ { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table);
+
+const mp_obj_type_t bleio_service_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Service,
+ .print = bleio_service_print,
+ .make_new = bleio_service_make_new,
+ .locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict
+};
diff --git a/shared-bindings/bleio/Service.h b/shared-bindings/bleio/Service.h
new file mode 100644
index 000000000..77c751829
--- /dev/null
+++ b/shared-bindings/bleio/Service.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
+
+#include "shared-module/bleio/Characteristic.h"
+#include "shared-module/bleio/Service.h"
+
+const mp_obj_type_t bleio_service_type;
+
+extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H
diff --git a/shared-bindings/bleio/UUID.c b/shared-bindings/bleio/UUID.c
new file mode 100644
index 000000000..7cef9a26f
--- /dev/null
+++ b/shared-bindings/bleio/UUID.c
@@ -0,0 +1,146 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Glenn Ruben Bakke
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "shared-bindings/bleio/UUID.h"
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`UUID` -- BLE UUID
+//| =========================================================
+//|
+//| Encapsulates both 16-bit and 128-bit UUIDs. Can be used for services,
+//| characteristics, descriptors and more.
+//|
+
+//| .. class:: UUID(uuid)
+//|
+//| Create a new UUID object encapsulating the uuid value.
+//| The value itself can be one of:
+//|
+//| - a `int` value in range of 0 to 0xFFFF
+//| - a `str` value in the format of '0xXXXX' for 16-bit or 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' for 128-bit
+//|
+//| :param int/str uuid: The uuid to encapsulate
+//|
+
+//| .. method:: __len__()
+//|
+//| Returns the uuid length in bits
+//|
+//| This allows you to:
+//|
+//| uuid = bleio.UUID(0x1801)
+//| print(len(uuid))
+//|
+
+//| .. attribute:: type
+//|
+//| The UUID type. One of:
+//|
+//| - `bleio.UUIDType.TYPE_16BIT`
+//| - `bleio.UUIDType.TYPE_128BIT`
+//|
+STATIC mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 1, 1, true);
+ bleio_uuid_obj_t *self = m_new_obj(bleio_uuid_obj_t);
+ self->base.type = &bleio_uuid_type;
+
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+
+ enum { ARG_uuid };
+ static const mp_arg_t allowed_args[] = {
+ { ARG_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ const mp_obj_t uuid = args[ARG_uuid].u_obj;
+
+ common_hal_bleio_uuid_construct(self, &uuid);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
+ bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ const bleio_uuid_type_t type = common_hal_bleio_uuid_get_type(self);
+ const uint8_t len = (type == UUID_TYPE_16BIT) ? 16 : 128;
+ switch (op) {
+ case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0);
+ case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len);
+ default: return MP_OBJ_NULL; // op not supported
+ }
+}
+
+STATIC void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ common_hal_bleio_uuid_print(self, print);
+}
+
+STATIC mp_obj_t bleio_uuid_get_type(mp_obj_t self_in) {
+ bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ const bleio_uuid_type_t type = common_hal_bleio_uuid_get_type(self);
+ if (type == UUID_TYPE_16BIT) {
+ return (mp_obj_t)&bleio_uuidtype_16bit_obj;
+ }
+
+ if (type == UUID_TYPE_128BIT) {
+ return (mp_obj_t)&bleio_uuidtype_128bit_obj;
+ }
+
+ return (mp_obj_t)&mp_const_none_obj;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(bleio_uuid_get_type_obj, bleio_uuid_get_type);
+
+const mp_obj_property_t bleio_uuid_type_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&bleio_uuid_get_type_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t bleio_uuid_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_uuid_type_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(bleio_uuid_locals_dict, bleio_uuid_locals_dict_table);
+
+const mp_obj_type_t bleio_uuid_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_UUID,
+ .print = bleio_uuid_print,
+ .make_new = bleio_uuid_make_new,
+ .unary_op = bleio_uuid_unary_op,
+ .locals_dict = (mp_obj_dict_t*)&bleio_uuid_locals_dict
+};
diff --git a/shared-bindings/bleio/UUID.h b/shared-bindings/bleio/UUID.h
new file mode 100644
index 000000000..d6fcbac1b
--- /dev/null
+++ b/shared-bindings/bleio/UUID.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H
+
+#include "common-hal/bleio/UUID.h"
+#include "shared-bindings/bleio/UUIDType.h"
+
+extern const mp_obj_type_t bleio_uuid_type;
+
+extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, const mp_obj_t *uuid);
+extern void common_hal_bleio_uuid_print(bleio_uuid_obj_t *self, const mp_print_t *print);
+extern bleio_uuid_type_t common_hal_bleio_uuid_get_type(bleio_uuid_obj_t *self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H
diff --git a/shared-bindings/bleio/UUIDType.c b/shared-bindings/bleio/UUIDType.c
new file mode 100644
index 000000000..e36d1f06d
--- /dev/null
+++ b/shared-bindings/bleio/UUIDType.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/bleio/UUIDType.h"
+
+//| .. currentmodule:: bleio
+//|
+//| :class:`UUIDType` -- defines the type of a BLE UUID
+//| =============================================================
+//|
+//| .. class:: bleio.UUIDType
+//|
+//| Enum-like class to define the type of a BLE UUID.
+//|
+//| .. data:: TYPE_16BIT
+//|
+//| The UUID is 16-bit
+//|
+//| .. data:: TYPE_128BIT
+//|
+//| The UUID is 128-bit
+//|
+const mp_obj_type_t bleio_uuidtype_type;
+
+const bleio_uuidtype_obj_t bleio_uuidtype_16bit_obj = {
+ { &bleio_uuidtype_type },
+};
+
+const bleio_uuidtype_obj_t bleio_uuidtype_128bit_obj = {
+ { &bleio_uuidtype_type },
+};
+
+STATIC const mp_rom_map_elem_t bleio_uuidtype_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_TYPE_16BIT), MP_ROM_PTR(&bleio_uuidtype_16bit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_TYPE_128BIT), MP_ROM_PTR(&bleio_uuidtype_128bit_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(bleio_uuidtype_locals_dict, bleio_uuidtype_locals_dict_table);
+
+STATIC void bleio_uuidtype_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ qstr type = MP_QSTR_TYPE_128BIT;
+ if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_uuidtype_16bit_obj)) {
+ type = MP_QSTR_TYPE_16BIT;
+ }
+ mp_printf(print, "%q.%q.%q", MP_QSTR_bleio, MP_QSTR_UUIDType, type);
+}
+
+const mp_obj_type_t bleio_uuidtype_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_UUIDType,
+ .print = bleio_uuidtype_print,
+ .locals_dict = (mp_obj_t)&bleio_uuidtype_locals_dict,
+};
diff --git a/shared-bindings/bleio/UUIDType.h b/shared-bindings/bleio/UUIDType.h
new file mode 100644
index 000000000..87bbf9b53
--- /dev/null
+++ b/shared-bindings/bleio/UUIDType.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUIDTYPE_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUIDTYPE_H
+
+#include "py/obj.h"
+
+typedef enum {
+ UUID_TYPE_16BIT,
+ UUID_TYPE_128BIT
+} bleio_uuid_type_t;
+
+extern const mp_obj_type_t bleio_uuidtype_type;
+
+typedef struct {
+ mp_obj_base_t base;
+} bleio_uuidtype_obj_t;
+
+extern const bleio_uuidtype_obj_t bleio_uuidtype_16bit_obj;
+extern const bleio_uuidtype_obj_t bleio_uuidtype_128bit_obj;
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUIDTYPE_H
diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c
index 475fb395a..98099422c 100644
--- a/shared-bindings/bleio/__init__.c
+++ b/shared-bindings/bleio/__init__.c
@@ -25,8 +25,18 @@
* THE SOFTWARE.
*/
-#include "py/obj.h"
#include "shared-bindings/bleio/__init__.h"
+#include "shared-bindings/bleio/Address.h"
+#include "shared-bindings/bleio/AddressType.h"
+#include "shared-bindings/bleio/AdvertisementData.h"
+#include "shared-bindings/bleio/Characteristic.h"
+#include "shared-bindings/bleio/Descriptor.h"
+#include "shared-bindings/bleio/Device.h"
+#include "shared-bindings/bleio/ScanEntry.h"
+#include "shared-bindings/bleio/Scanner.h"
+#include "shared-bindings/bleio/Service.h"
+#include "shared-bindings/bleio/UUID.h"
+#include "shared-bindings/bleio/UUIDType.h"
//| :mod:`bleio` --- Bluetooth Low Energy functionality
//| ================================================================
@@ -42,7 +52,18 @@
//| .. toctree::
//| :maxdepth: 3
//|
+//| Address
+//| AddressType
+//| AdvertisementData
//| Adapter
+//| Characteristic
+//| Descriptor
+//| Device
+//| ScanEntry
+//| Scanner
+//| Service
+//| UUID
+//| UUIDType
//|
//| .. attribute:: adapter
//|
@@ -52,8 +73,23 @@
//|
STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) },
- { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) },
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) },
+ { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) },
+ { MP_ROM_QSTR(MP_QSTR_AdvertisementData), MP_ROM_PTR(&bleio_advertisementdata_type) },
+ { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) },
+ { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },
+ { MP_ROM_QSTR(MP_QSTR_Device), MP_ROM_PTR(&bleio_device_type) },
+ { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
+ { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) },
+ { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) },
+ { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) },
+
+ // Properties
+ { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) },
+
+ // Enum-like Classes.
+ { MP_ROM_QSTR(MP_QSTR_AddressType), MP_ROM_PTR(&bleio_addresstype_type) },
+ { MP_ROM_QSTR(MP_QSTR_UUIDType), MP_ROM_PTR(&bleio_uuidtype_type) },
};
STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table);
diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c
index 7983a3a56..d30bbbe06 100644
--- a/shared-bindings/busio/SPI.c
+++ b/shared-bindings/busio/SPI.c
@@ -136,19 +136,26 @@ static void check_lock(busio_spi_obj_t *self) {
//| .. method:: SPI.configure(\*, baudrate=100000, polarity=0, phase=0, bits=8)
//|
-//| Configures the SPI bus. Only valid when locked.
+//| Configures the SPI bus. The SPI object must be locked.
//|
//| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower
//| due to the granularity of available clock settings.
//| Check the `frequency` attribute for the actual clock rate.
-//| **Note:** on the SAMD21, it is possible to set the baud rate to 24 MHz, but that
-//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is
-//| within spec for the SAMD21.
//| :param int polarity: the base state of the clock line (0 or 1)
//| :param int phase: the edge of the clock that data is captured. First (0)
//| or second (1). Rising or falling depends on clock polarity.
//| :param int bits: the number of bits per word
//|
+//| .. note:: On the SAMD21, it is possible to set the baudrate to 24 MHz, but that
+//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is
+//| within spec for the SAMD21.
+//|
+//| .. note:: On the nRF52832, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz,
+//| and 8MHz. On the nRF52840, 16MHz and 32MHz are also available, but only on the first
+//| `busio.SPI` object you create. Two more ``busio.SPI`` objects can be created, but they are restricted
+//| to 8MHz maximum. This is a hardware restriction: there is only one high-speed SPI peripheral.
+//| If you pick a a baudrate other than one of these, the nearest lower
+//| baudrate will be chosen, with a minimum of 125kHz.
STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits };
static const mp_arg_t allowed_args[] = {
diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h
index 555f32c92..2d12b8b76 100644
--- a/shared-bindings/busio/SPI.h
+++ b/shared-bindings/busio/SPI.h
@@ -61,4 +61,7 @@ extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_o
// Return actual SPI bus frequency.
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self);
+// This is used by the supervisor to claim SPI devices indefinitely.
+extern void common_hal_busio_spi_never_reset(busio_spi_obj_t *self);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H
diff --git a/shared-bindings/help.c b/shared-bindings/help.c
index 78301a91a..e0770ff3c 100644
--- a/shared-bindings/help.c
+++ b/shared-bindings/help.c
@@ -24,8 +24,6 @@
* THE SOFTWARE.
*/
-#include "genhdr/mpversion.h"
-
//| :func:`help` - Built-in method to provide helpful information
//| ==============================================================
//|
@@ -34,12 +32,3 @@
//| Prints a help method about the given object. When ``object`` is none,
//| prints general port information.
//|
-
-// TODO(tannewt): Figure out how to translate this. Its weird because its a global string.
-
-const char circuitpython_help_text[] =
- "Welcome to Adafruit CircuitPython " MICROPY_GIT_TAG "!\r\n"
- "\r\n"
- "Please visit learn.adafruit.com/category/circuitpython for project guides.\r\n"
- "\r\n"
- "To list built-in modules please do `help(\"modules\")`.\r\n";
diff --git a/shared-bindings/network/__init__.c b/shared-bindings/network/__init__.c
new file mode 100644
index 000000000..69f8bea60
--- /dev/null
+++ b/shared-bindings/network/__init__.c
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "py/mperrno.h"
+#include "lib/netutils/netutils.h"
+
+#include "shared-bindings/network/__init__.h"
+
+#if MICROPY_PY_NETWORK
+
+//| :mod:`network` --- Network Interface Management
+//| ===============================================
+//|
+//| .. module:: network
+//| :synopsis: Network Interface Management
+//| :platform: SAMD
+//|
+//| This module provides a registry of configured NICs.
+//| It is used by the 'socket' module to look up a suitable
+//| NIC when a socket is created.
+//|
+//| .. function:: route
+//|
+//| Returns a list of all configured NICs.
+//|
+
+STATIC mp_obj_t network_route(void) {
+ return MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route);
+
+STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
+ { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
+
+const mp_obj_module_t network_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mp_module_network_globals,
+};
+
+#endif // MICROPY_PY_NETWORK
diff --git a/shared-bindings/network/__init__.h b/shared-bindings/network/__init__.h
new file mode 100644
index 000000000..4fe5e75a3
--- /dev/null
+++ b/shared-bindings/network/__init__.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_NETWORK___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_NETWORK___INIT___H
+
+// nothing
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_NETWORK___INIT___H
diff --git a/shared-bindings/pulseio/PWMOut.c b/shared-bindings/pulseio/PWMOut.c
index 9b7094b4e..362b8123d 100644
--- a/shared-bindings/pulseio/PWMOut.c
+++ b/shared-bindings/pulseio/PWMOut.c
@@ -192,7 +192,7 @@ STATIC mp_obj_t pulseio_pwmout_obj_set_frequency(mp_obj_t self_in, mp_obj_t freq
raise_error_if_deinited(common_hal_pulseio_pwmout_deinited(self));
if (!common_hal_pulseio_pwmout_get_variable_frequency(self)) {
mp_raise_AttributeError(translate(
- "PWM frequency not writeable when variable_frequency is False on "
+ "PWM frequency not writable when variable_frequency is False on "
"construction."));
}
common_hal_pulseio_pwmout_set_frequency(self, mp_obj_get_int(frequency));
diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c
index 1c97c37c3..e9834c12a 100644
--- a/shared-bindings/pulseio/PulseOut.c
+++ b/shared-bindings/pulseio/PulseOut.c
@@ -47,7 +47,7 @@
//|
//| .. class:: PulseOut(carrier)
//|
-//| Create a PulseOut object associated with the given PWM out experience.
+//| Create a PulseOut object associated with the given PWMout object.
//|
//| :param ~pulseio.PWMOut carrier: PWMOut that is set to output on the desired pin.
//|
@@ -57,9 +57,10 @@
//| import pulseio
//| import board
//|
-//| pwm = pulseio.PWMOut(board.D13, duty_cycle=2 ** 15)
+//| # 50% duty cycle at 38kHz.
+//| pwm = pulseio.PWMOut(board.D13, frequency=38000, duty_cycle=32768)
//| pulse = pulseio.PulseOut(pwm)
-//| # on off on off on
+//| # on off on off on
//| pulses = array.array('H', [65000, 1000, 65000, 65000, 1000])
//| pulse.send(pulses)
//|
diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c
new file mode 100644
index 000000000..d860c40c8
--- /dev/null
+++ b/shared-bindings/socket/__init__.c
@@ -0,0 +1,559 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Damien P. George
+ * 2018 Nick Moore for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "py/objtuple.h"
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "py/mperrno.h"
+#include "lib/netutils/netutils.h"
+
+#include "shared-module/network/__init__.h"
+
+//| :mod:`socket` --- TCP, UDP and RAW socket support
+//| =================================================
+//|
+//| .. module:: socket
+//| :synopsis: TCP, UDP and RAW sockets
+//| :platform: SAMD21, SAMD51
+//|
+//| Create TCP, UDP and RAW sockets for communicating over the Internet.
+//|
+
+STATIC const mp_obj_type_t socket_type;
+
+//| .. currentmodule:: socket
+//|
+//| .. class:: socket(family, type, proto, ...)
+//|
+//| Create a new socket
+//|
+//| :param ~int family: AF_INET or AF_INET6
+//| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
+//| :param ~int proto: IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW (ignored)
+//|
+
+STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 0, 4, false);
+
+ // create socket object (not bound to any NIC yet)
+ mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
+ s->base.type = &socket_type;
+ s->nic = MP_OBJ_NULL;
+ s->nic_type = NULL;
+ s->u_param.domain = MOD_NETWORK_AF_INET;
+ s->u_param.type = MOD_NETWORK_SOCK_STREAM;
+ s->u_param.fileno = -1;
+ if (n_args >= 1) {
+ s->u_param.domain = mp_obj_get_int(args[0]);
+ if (n_args >= 2) {
+ s->u_param.type = mp_obj_get_int(args[1]);
+ if (n_args >= 4) {
+ s->u_param.fileno = mp_obj_get_int(args[3]);
+ }
+ }
+ }
+
+ return MP_OBJ_FROM_PTR(s);
+}
+
+STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
+ if (self->nic == MP_OBJ_NULL) {
+ // select NIC based on IP
+ self->nic = network_module_find_nic(ip);
+ self->nic_type = (mod_network_nic_type_t*)mp_obj_get_type(self->nic);
+
+ // call the NIC to open the socket
+ int _errno;
+ if (self->nic_type->socket(self, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+ }
+}
+
+//| .. method:: bind(address)
+//|
+//| Bind a socket to an address
+//|
+//| :param ~tuple address: tuple of (remote_address, remote_port)
+//|
+
+STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ // get address
+ uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+ mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
+
+ // check if we need to select a NIC
+ socket_select_nic(self, ip);
+
+ // call the NIC to bind the socket
+ int _errno;
+ if (self->nic_type->bind(self, ip, port, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
+
+//| .. method:: listen(backlog)
+//|
+//| Set socket to listen for incoming connections
+//|
+//| :param ~int backlog: length of backlog queue for waiting connetions
+//|
+
+STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ // TODO I think we can listen even if not bound...
+ mp_raise_OSError(MP_ENOTCONN);
+ }
+
+ int _errno;
+ if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
+
+//| .. method:: accept()
+//|
+//| Accept a connection on a listening socket of type SOCK_STREAM,
+//| creating a new socket of type SOCK_STREAM.
+//| Returns a tuple of (new_socket, remote_address)
+//|
+
+STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ // create new socket object
+ // starts with empty NIC so that finaliser doesn't run close() method if accept() fails
+ mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t);
+ socket2->base.type = &socket_type;
+ socket2->nic = MP_OBJ_NULL;
+ socket2->nic_type = NULL;
+
+ // accept incoming connection
+ uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+ mp_uint_t port;
+ int _errno;
+ if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ // new socket has valid state, so set the NIC to the same as parent
+ socket2->nic = self->nic;
+ socket2->nic_type = self->nic_type;
+
+ // make the return value
+ mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
+ client->items[0] = MP_OBJ_FROM_PTR(socket2);
+ client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
+
+ return MP_OBJ_FROM_PTR(client);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
+
+//| .. method:: connect(address)
+//|
+//| Connect a socket to a remote address
+//|
+//| :param ~tuple address: tuple of (remote_address, remote_port)
+//|
+
+STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ // get address
+ uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+ mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
+
+ // check if we need to select a NIC
+ socket_select_nic(self, ip);
+
+ // call the NIC to connect the socket
+ int _errno;
+ if (self->nic_type->connect(self, ip, port, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
+
+//| .. method:: send(bytes)
+//|
+//| Send some bytes to the connected remote address.
+//| Suits sockets of type SOCK_STREAM
+//|
+//| :param ~bytes bytes: some bytes to send
+//|
+
+STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ mp_raise_OSError(MP_EPIPE);
+ }
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+ int _errno;
+ mp_int_t ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ }
+ return mp_obj_new_int_from_uint(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
+
+//| .. method:: recv(bufsize)
+//|
+//| Reads some bytes from the connected remote address.
+//| Suits sockets of type SOCK_STREAM
+//| Returns a bytes() of length <= bufsize
+//|
+//| :param ~int bufsize: maximum number of bytes to receive
+
+STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ mp_raise_OSError(MP_ENOTCONN);
+ }
+ mp_int_t len = mp_obj_get_int(len_in);
+ vstr_t vstr;
+ vstr_init_len(&vstr, len);
+ int _errno;
+ mp_int_t ret = self->nic_type->recv(self, (byte*)vstr.buf, len, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ }
+ if (ret == 0) {
+ return mp_const_empty_bytes;
+ }
+ vstr.len = ret;
+ return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
+
+//| .. method:: sendto(bytes, address)
+//|
+//| Send some bytes to a specific address.
+//| Suits sockets of type SOCK_DGRAM
+//|
+//| :param ~bytes bytes: some bytes to send
+//| :param ~tuple address: tuple of (remote_address, remote_port)
+//|
+
+STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ // get the data
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
+
+ // get address
+ uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+ mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
+
+ // check if we need to select a NIC
+ socket_select_nic(self, ip);
+
+ // call the NIC to sendto
+ int _errno;
+ mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ }
+
+ return mp_obj_new_int(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
+
+//| .. method:: recvfrom(bufsize)
+//|
+//| Reads some bytes from the connected remote address.
+//| Suits sockets of type SOCK_STREAM
+//|
+//| Returns a tuple containing
+//| * a bytes() of length <= bufsize
+//| * a remote_address, which is a tuple of ip address and port number
+//|
+//| :param ~int bufsize: maximum number of bytes to receive
+//|
+
+STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ mp_raise_OSError(MP_ENOTCONN);
+ }
+ vstr_t vstr;
+ vstr_init_len(&vstr, mp_obj_get_int(len_in));
+ byte ip[4];
+ mp_uint_t port;
+ int _errno;
+ mp_int_t ret = self->nic_type->recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ }
+ mp_obj_t tuple[2];
+ if (ret == 0) {
+ tuple[0] = mp_const_empty_bytes;
+ } else {
+ vstr.len = ret;
+ tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ }
+ tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
+ return mp_obj_new_tuple(2, tuple);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
+
+//| .. method:: setsockopt(level, optname, value)
+//|
+//| Sets socket options
+//|
+
+STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+
+ mp_int_t level = mp_obj_get_int(args[1]);
+ mp_int_t opt = mp_obj_get_int(args[2]);
+
+ const void *optval;
+ mp_uint_t optlen;
+ mp_int_t val;
+ if (mp_obj_is_integer(args[3])) {
+ val = mp_obj_get_int_truncated(args[3]);
+ optval = &val;
+ optlen = sizeof(val);
+ } else {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
+ optval = bufinfo.buf;
+ optlen = bufinfo.len;
+ }
+
+ int _errno;
+ if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
+
+//| .. method:: settimeout(value)
+//|
+//| Set the timeout value for this socket.
+//|
+//| :param ~int value: timeout in seconds. 0 means non-blocking. None means block indefinitely.
+//|
+
+STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ mp_raise_OSError(MP_ENOTCONN);
+ }
+ mp_uint_t timeout;
+ if (timeout_in == mp_const_none) {
+ timeout = -1;
+ } else {
+ #if MICROPY_PY_BUILTINS_FLOAT
+ timeout = 1000 * mp_obj_get_float(timeout_in);
+ #else
+ timeout = 1000 * mp_obj_get_int(timeout_in);
+ #endif
+ }
+ int _errno;
+ if (self->nic_type->settimeout(self, timeout, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
+
+//| .. method:: setblocking(flag)
+//|
+//| Set the blocking behaviour of this socket.
+//|
+//| :param ~bool flag: False means non-blocking, True means block indefinitely.
+//|
+
+// method socket.setblocking(flag)
+STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) {
+ if (mp_obj_is_true(blocking)) {
+ return socket_settimeout(self_in, mp_const_none);
+ } else {
+ return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0));
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
+
+STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) },
+ { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) },
+ { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) },
+ { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) },
+ { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) },
+ { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
+
+mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (request == MP_STREAM_CLOSE) {
+ if (self->nic != MP_OBJ_NULL) {
+ self->nic_type->close(self);
+ self->nic = MP_OBJ_NULL;
+ }
+ return 0;
+ }
+ return self->nic_type->ioctl(self, request, arg, errcode);
+}
+
+STATIC const mp_stream_p_t socket_stream_p = {
+ .ioctl = socket_ioctl,
+ .is_text = false,
+};
+
+STATIC const mp_obj_type_t socket_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_socket,
+ .make_new = socket_make_new,
+ .protocol = &socket_stream_p,
+ .locals_dict = (mp_obj_dict_t*)&socket_locals_dict,
+};
+
+//| .. function:: getaddrinfo(host, port)
+//|
+//| Gets the address information for a hostname and port
+//|
+//| Returns the appropriate family, socket type, socket protocol and
+//| address information to call socket.socket() and socket.connect() with,
+//| as a tuple.
+//|
+
+STATIC mp_obj_t socket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
+ size_t hlen;
+ const char *host = mp_obj_str_get_data(host_in, &hlen);
+ mp_int_t port = mp_obj_get_int(port_in);
+ uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+ bool have_ip = false;
+
+ if (hlen > 0) {
+ // check if host is already in IP form
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ netutils_parse_ipv4_addr(host_in, out_ip, NETUTILS_BIG);
+ have_ip = true;
+ nlr_pop();
+ } else {
+ // swallow exception: host was not in IP form so need to do DNS lookup
+ }
+ }
+
+ if (!have_ip) {
+ // find a NIC that can do a name lookup
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
+ mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
+ mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic);
+ if (nic_type->gethostbyname != NULL) {
+ int ret = nic_type->gethostbyname(nic, host, hlen, out_ip);
+ if (ret != 0) {
+ mp_raise_OSError(ret);
+ }
+ have_ip = true;
+ break;
+ }
+ }
+ }
+
+ if (!have_ip) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, translate("no available NIC")));
+ }
+
+ mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
+ tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
+ tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
+ tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
+ tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
+ tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG);
+ return mp_obj_new_list(1, (mp_obj_t*)&tuple);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_getaddrinfo_obj, socket_getaddrinfo);
+
+STATIC const mp_rom_map_elem_t socket_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) },
+
+ { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) },
+ { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&socket_getaddrinfo_obj) },
+
+ // class constants
+ { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(MOD_NETWORK_AF_INET) },
+ { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) },
+
+ { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) },
+
+ /*
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(MOD_NETWORK_IPPROTO_IP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_ICMP), MP_ROM_INT(MOD_NETWORK_IPPROTO_ICMP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV4), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV4) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(MOD_NETWORK_IPPROTO_TCP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(MOD_NETWORK_IPPROTO_UDP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV6), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV6) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_RAW), MP_ROM_INT(MOD_NETWORK_IPPROTO_RAW) },
+ */
+};
+
+STATIC MP_DEFINE_CONST_DICT(socket_globals, socket_globals_table);
+
+const mp_obj_module_t socket_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&socket_globals,
+};
diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c
index b061595cf..5ba2198e1 100755
--- a/shared-bindings/supervisor/Runtime.c
+++ b/shared-bindings/supervisor/Runtime.c
@@ -80,8 +80,34 @@ const mp_obj_property_t supervisor_serial_connected_obj = {
(mp_obj_t)&mp_const_none_obj},
};
+
+//| .. attribute:: runtime.serial_bytes_available
+//|
+//| Returns the whether any bytes are available to read
+//| on the USB serial input. Allows for polling to see whether
+//| to call the built-in input() or wait. (read-only)
+//|
+STATIC mp_obj_t supervisor_get_serial_bytes_available(mp_obj_t self){
+ if (!common_hal_get_serial_bytes_available()) {
+ return mp_const_false;
+ }
+ else {
+ return mp_const_true;
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_1(supervisor_get_serial_bytes_available_obj, supervisor_get_serial_bytes_available);
+
+const mp_obj_property_t supervisor_serial_bytes_available_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&supervisor_get_serial_bytes_available_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+
STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_serial_connected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_serial_bytes_available), MP_ROM_PTR(&supervisor_serial_bytes_available_obj) },
};
STATIC MP_DEFINE_CONST_DICT(supervisor_runtime_locals_dict, supervisor_runtime_locals_dict_table);
diff --git a/shared-bindings/supervisor/Runtime.h b/shared-bindings/supervisor/Runtime.h
index 4a67925ec..864b070cd 100755
--- a/shared-bindings/supervisor/Runtime.h
+++ b/shared-bindings/supervisor/Runtime.h
@@ -35,6 +35,8 @@ const mp_obj_type_t supervisor_runtime_type;
bool common_hal_get_serial_connected(void);
+bool common_hal_get_serial_bytes_available(void);
+
//TODO: placeholders for future functions
//bool common_hal_get_repl_active(void);
//bool common_hal_get_usb_enumerated(void);
diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c
index 4d9554569..f97ad4a5d 100644
--- a/shared-bindings/time/__init__.c
+++ b/shared-bindings/time/__init__.c
@@ -206,6 +206,19 @@ STATIC mp_obj_t time_time(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
+//| .. method:: monotonic_ns()
+//|
+//| Return the time of the specified clock clk_id in nanoseconds.
+//|
+//| :return: the current time
+//| :rtype: int
+//|
+STATIC mp_obj_t time_monotonic_ns(void) {
+ uint64_t time64 = common_hal_time_monotonic() * 1000000llu;
+ return mp_obj_new_int_from_ll((long long) time64);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_ns_obj, time_monotonic_ns);
+
//| .. method:: localtime([secs])
//|
//| Convert a time expressed in seconds since Jan 1, 1970 to a struct_time in
@@ -280,6 +293,7 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
#endif // MICROPY_PY_COLLECTIONS
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) },
+ { MP_ROM_QSTR(MP_QSTR_monotonic_ns), MP_ROM_PTR(&time_monotonic_ns_obj) },
#endif
};
diff --git a/shared-bindings/usb_hid/Device.h b/shared-bindings/usb_hid/Device.h
index 2bc553c4a..cb9a64b5e 100644
--- a/shared-bindings/usb_hid/Device.h
+++ b/shared-bindings/usb_hid/Device.h
@@ -27,7 +27,7 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_USB_HID_DEVICE_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_USB_HID_DEVICE_H
-#include "common-hal/usb_hid/Device.h"
+#include "shared-module/usb_hid/Device.h"
const mp_obj_type_t usb_hid_device_type;
diff --git a/shared-bindings/wiznet/__init__.c b/shared-bindings/wiznet/__init__.c
new file mode 100644
index 000000000..e230deecc
--- /dev/null
+++ b/shared-bindings/wiznet/__init__.c
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "py/objlist.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
+
+#include "shared-module/network/__init__.h"
+
+//| :mod:`wiznet` --- Support for WizNet hardware
+//| =============================================
+//|
+//| .. module:: wiznet
+//| :synopsis: Support for WizNet hardware
+//| :platform: SAMD
+//|
+//| Support for WizNet hardware, including the WizNet 5500 Ethernet adaptor.
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| wiznet5k
+//|
+
+extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k;
+
+STATIC const mp_rom_map_elem_t mp_module_wiznet_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wiznet) },
+#ifdef MICROPY_PY_WIZNET5K
+ { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
+#endif // MICROPY_PY_WIZNET5K
+};
+STATIC MP_DEFINE_CONST_DICT(mp_module_wiznet_globals, mp_module_wiznet_globals_table);
+
+const mp_obj_module_t wiznet_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mp_module_wiznet_globals,
+};
+
diff --git a/shared-bindings/wiznet/wiznet5k.c b/shared-bindings/wiznet/wiznet5k.c
new file mode 100644
index 000000000..4e5fff869
--- /dev/null
+++ b/shared-bindings/wiznet/wiznet5k.c
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "py/objlist.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "py/mperrno.h"
+#include "py/mphal.h"
+#include "lib/netutils/netutils.h"
+
+#if MICROPY_PY_WIZNET5K
+
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/digitalio/DriveMode.h"
+#include "shared-bindings/busio/SPI.h"
+
+#include "shared-module/network/__init__.h"
+#include "shared-module/wiznet/wiznet5k.h"
+
+//| .. currentmodule:: wiznet
+//|
+//| :class:`WIZNET5K` -- wrapper for Wiznet 5500 Ethernet interface
+//| ===============================================================
+//|
+//| .. class:: WIZNET5K(spi, cs, rst)
+//|
+//| Create a new WIZNET5500 interface using the specified pins
+//|
+//| :param spi: spi bus to use
+//| :param cs: pin to use for Chip Select
+//| :param rst: pin to sue for Reset
+//|
+
+STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ // check arguments
+ mp_arg_check_num(n_args, n_kw, 3, 3, false);
+
+ return wiznet5k_create(args[0], args[1], args[2]);
+}
+
+//| .. attribute:: connected
+//|
+//| is this device physically connected?
+//|
+
+STATIC mp_obj_t wiznet5k_connected_get_value(mp_obj_t self_in) {
+ (void)self_in;
+ return mp_obj_new_bool(wizphy_getphylink() == PHY_LINK_ON);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_connected_get_value_obj, wiznet5k_connected_get_value);
+
+const mp_obj_property_t wiznet5k_connected_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&wiznet5k_connected_get_value_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. attribute:: dhcp
+//|
+//| is DHCP active on this device? (set to true to activate DHCP, false to turn it off)
+//|
+
+STATIC mp_obj_t wiznet5k_dhcp_get_value(mp_obj_t self_in) {
+ (void)self_in;
+ return mp_obj_new_bool(wiznet5k_check_dhcp());
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_dhcp_get_value_obj, wiznet5k_dhcp_get_value);
+
+STATIC mp_obj_t wiznet5k_dhcp_set_value(mp_obj_t self_in, mp_obj_t value) {
+ (void)self_in;
+ if (mp_obj_is_true(value)) {
+ wiznet5k_start_dhcp();
+ } else {
+ wiznet5k_stop_dhcp();
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_dhcp_set_value_obj, wiznet5k_dhcp_set_value);
+
+const mp_obj_property_t wiznet5k_dhcp_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&wiznet5k_dhcp_get_value_obj,
+ (mp_obj_t)&wiznet5k_dhcp_set_value_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. method:: ifconfig(...)
+//|
+//| Called without parameters, returns a tuple of
+//| (ip_address, subnet_mask, gateway_address, dns_server)
+//|
+//| Or can be called with the same tuple to set those parameters.
+//|
+
+STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) {
+ wiz_NetInfo netinfo;
+ ctlnetwork(CN_GET_NETINFO, &netinfo);
+ if (n_args == 1) {
+ // get
+ mp_obj_t tuple[4] = {
+ netutils_format_ipv4_addr(netinfo.ip, NETUTILS_BIG),
+ netutils_format_ipv4_addr(netinfo.sn, NETUTILS_BIG),
+ netutils_format_ipv4_addr(netinfo.gw, NETUTILS_BIG),
+ netutils_format_ipv4_addr(netinfo.dns, NETUTILS_BIG),
+ };
+ return mp_obj_new_tuple(4, tuple);
+ } else {
+ // set
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(args[1], 4, &items);
+ netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG);
+ netutils_parse_ipv4_addr(items[1], netinfo.sn, NETUTILS_BIG);
+ netutils_parse_ipv4_addr(items[2], netinfo.gw, NETUTILS_BIG);
+ netutils_parse_ipv4_addr(items[3], netinfo.dns, NETUTILS_BIG);
+ ctlnetwork(CN_SET_NETINFO, &netinfo);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig);
+
+STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&wiznet5k_connected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dhcp), MP_ROM_PTR(&wiznet5k_dhcp_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table);
+
+const mod_network_nic_type_t mod_network_nic_type_wiznet5k = {
+ .base = {
+ { &mp_type_type },
+ .name = MP_QSTR_WIZNET5K,
+ .make_new = wiznet5k_make_new,
+ .locals_dict = (mp_obj_dict_t*)&wiznet5k_locals_dict,
+ },
+ .gethostbyname = wiznet5k_gethostbyname,
+ .socket = wiznet5k_socket_socket,
+ .close = wiznet5k_socket_close,
+ .bind = wiznet5k_socket_bind,
+ .listen = wiznet5k_socket_listen,
+ .accept = wiznet5k_socket_accept,
+ .connect = wiznet5k_socket_connect,
+ .send = wiznet5k_socket_send,
+ .recv = wiznet5k_socket_recv,
+ .sendto = wiznet5k_socket_sendto,
+ .recvfrom = wiznet5k_socket_recvfrom,
+ .setsockopt = wiznet5k_socket_setsockopt,
+ .settimeout = wiznet5k_socket_settimeout,
+ .ioctl = wiznet5k_socket_ioctl,
+ .timer_tick = wiznet5k_socket_timer_tick,
+};
+
+#endif // MICROPY_PY_WIZNET5K