diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c393afe7d8..10c34355d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -158,6 +158,7 @@ jobs: - "trinket_m0_haxpress" - "uchip" - "ugame10" + - "winterbloom_sol" steps: - name: Set up Python 3.5 diff --git a/lib/utils/interrupt_char.c b/lib/utils/interrupt_char.c index 91ee5c80ef..da7f702544 100644 --- a/lib/utils/interrupt_char.c +++ b/lib/utils/interrupt_char.c @@ -49,7 +49,7 @@ void mp_keyboard_interrupt(void) { // Check to see if we've been CTRL-C'ed by autoreload or the user. bool mp_hal_is_interrupted(void) { - return MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); + return MP_STATE_VM(mp_pending_exception) != NULL; } #endif diff --git a/locale/ID.po b/locale/ID.po index 63e3466b6e..9c70789af6 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -261,6 +261,10 @@ msgstr "Semua timer untuk pin ini sedang digunakan" msgid "All timers in use" msgstr "Semua timer sedang digunakan" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "fungsionalitas AnalogOut tidak didukung" @@ -329,6 +333,11 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -465,6 +474,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -507,7 +522,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy msgid "Data too large for advertisement packet" msgstr "Tidak bisa menyesuaikan data ke dalam paket advertisment" @@ -554,10 +569,6 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -567,7 +578,7 @@ msgstr "" msgid "Expected a UUID" msgstr "" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -576,6 +587,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -586,20 +602,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Gagal untuk mendapatkan mutex, status: 0x%08lX" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Gagal untuk menambahkan karakteristik, status: 0x%08lX" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Gagal untuk menambahkan layanan, status: 0x%08lX" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Gagal untuk mengalokasikan buffer RX" @@ -611,25 +621,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Gagal untuk megalokasikan buffer RX dari %d byte" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Gagal untuk merubah status softdevice, error: 0x%08lX" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Gagal untuk menemukan layanan, status: 0x%08lX" @@ -649,7 +656,7 @@ msgstr "Gagal untuk mendapatkan status softdevice, error: 0x%08lX" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -658,8 +665,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Gagal untuk membaca nilai atribut, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -679,35 +685,27 @@ msgstr "Gagal untuk menambahkan Vendor Spesific UUID, status: 0x%08lX" msgid "Failed to release mutex, err 0x%04x" msgstr "Gagal untuk melepaskan mutex, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Gagal untuk memulai advertisement, status: 0x%08lX" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Gagal untuk melakukan scanning, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1004,9 +1002,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Tidak dapat menyambungkan ke AP" @@ -1081,6 +1078,10 @@ msgstr "Tambahkan module apapun pada filesystem\n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1151,6 +1152,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "Nilai sampel terlalu tinggi. Nilai harus kurang dari %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1165,11 +1170,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Dukungan soft device, id: 0x%08lX, pc: 0x%08l" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Memisahkan dengan menggunakan sub-captures" @@ -1984,7 +1984,7 @@ msgstr "" msgid "integer required" msgstr "" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2161,11 +2161,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "keyword harus berupa string" - #: py/runtime.c msgid "name not defined" msgstr "" @@ -2216,7 +2211,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2700,7 +2695,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2770,10 +2765,22 @@ msgstr "" #~ msgid "Failed to acquire mutex" #~ msgstr "Gagal untuk mendapatkan mutex, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Gagal untuk menambahkan karakteristik, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Gagal untuk menambahkan layanan, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Gagal untuk menambahkan layanan, status: 0x%08lX" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Gagal untuk merubah status softdevice, error: 0x%08lX" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "Gagal untuk menyambungkan, status: 0x%08lX" @@ -2782,6 +2789,10 @@ msgstr "" #~ msgid "Failed to continue scanning" #~ msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Gagal untuk membuat mutex, status: 0x%08lX" @@ -2802,6 +2813,10 @@ msgstr "" #~ msgid "Failed to start advertising" #~ msgstr "Gagal untuk memulai advertisement, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Gagal untuk memulai advertisement, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Gagal untuk melakukan scanning, status: 0x%08lX" @@ -2810,6 +2825,10 @@ msgstr "" #~ msgid "Failed to stop advertising" #~ msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX" + #~ msgid "GPIO16 does not support pull up." #~ msgstr "GPIO16 tidak mendukung pull up" @@ -2859,6 +2878,10 @@ msgstr "" #~ msgid "STA required" #~ msgstr "STA dibutuhkan" +#, fuzzy, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Dukungan soft device, id: 0x%08lX, pc: 0x%08l" + #~ msgid "UART(%d) does not exist" #~ msgstr "UART(%d) tidak ada" @@ -2936,6 +2959,10 @@ msgstr "" #~ msgid "memory allocation failed, allocating %u bytes for native code" #~ msgstr "alokasi memori gagal, mengalokasikan %u byte untuk kode native" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "keyword harus berupa string" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "tidak valid channel ADC: %d" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index d709a69cc9..34aa3ff0aa 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -259,6 +259,10 @@ msgstr "" msgid "All timers in use" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "" @@ -325,6 +329,11 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -455,6 +464,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -497,7 +512,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "" @@ -543,10 +558,6 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -556,7 +567,7 @@ msgstr "" msgid "Expected a UUID" msgstr "" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -565,6 +576,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -575,8 +591,7 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -584,11 +599,6 @@ msgstr "" msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "" @@ -600,24 +610,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "" @@ -634,7 +642,7 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -643,8 +651,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -664,34 +671,26 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -989,9 +988,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1065,6 +1063,10 @@ msgstr "" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1131,6 +1133,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1145,11 +1151,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "" @@ -1950,7 +1951,7 @@ msgstr "" msgid "integer required" msgstr "" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2127,10 +2128,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "" - #: py/runtime.c msgid "name not defined" msgstr "" @@ -2181,7 +2178,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2663,7 +2660,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" diff --git a/locale/de_DE.po b/locale/de_DE.po index 971687d19f..afe97ff9f8 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: Pascal Deneaux\n" "Language-Team: Sebastian Plamauer, Pascal Deneaux\n" @@ -261,6 +261,10 @@ msgstr "Alle timer für diesen Pin werden bereits benutzt" msgid "All timers in use" msgstr "Alle timer werden benutzt" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "AnalogOut-Funktion wird nicht unterstützt" @@ -329,6 +333,11 @@ msgstr "Die Helligkeit muss zwischen 0 und 255 liegen" msgid "Brightness not adjustable" msgstr "Die Helligkeit ist nicht einstellbar" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -459,6 +468,12 @@ msgstr "Der Befehl muss zwischen 0 und 255 liegen" msgid "Command must be an int between 0 and 255" msgstr "Der Befehl muss ein int zwischen 0 und 255 sein" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Beschädigte .mpy Datei" @@ -501,7 +516,7 @@ msgstr "Data 0 pin muss am Byte ausgerichtet sein" msgid "Data chunk must follow fmt chunk" msgstr "Dem fmt Block muss ein Datenblock folgen" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Zu vielen Daten für das advertisement packet" @@ -547,10 +562,6 @@ msgstr "Erwartet ein(e) %q" msgid "Expected a Characteristic" msgstr "Characteristic wird erwartet" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "Ein Peripheriegerät wird erwartet" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Ein Service wird erwartet" @@ -560,7 +571,7 @@ msgstr "Ein Service wird erwartet" msgid "Expected a UUID" msgstr "Eine UUID wird erwartet" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "Erwartet eine Adresse" @@ -569,6 +580,11 @@ msgstr "Erwartet eine Adresse" msgid "Expected tuple of length %d, got %d" msgstr "Habe ein Tupel der Länge %d erwartet aber %d erhalten" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "Kommando nicht gesendet." @@ -579,20 +595,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Mutex konnte nicht akquiriert werden. Status: 0x%04x" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Hinzufügen des Characteristic ist gescheitert. Status: 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "Deskriptor konnte nicht hinzugefügt werden. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Dienst konnte nicht hinzugefügt werden. Status: 0x%04x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Konnte keinen RX Buffer allozieren" @@ -604,24 +614,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Konnte keine RX Buffer mit %d allozieren" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" -msgstr "Fehler beim Ändern des Softdevice-Status" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Verbindung nicht erfolgreich: timeout" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Der Scanvorgang kann nicht fortgesetzt werden. Status: 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "Es konnten keine Dienste gefunden werden" @@ -638,7 +646,7 @@ msgstr "Fehler beim Abrufen des Softdevice-Status" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "Koppeln fehlgeschlagen" @@ -647,8 +655,7 @@ msgstr "Koppeln fehlgeschlagen" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Kann CCCD value nicht lesen. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Kann Attributwert nicht lesen, Status: 0x%04x" @@ -668,35 +675,27 @@ msgstr "Kann keine herstellerspezifische UUID hinzufügen. Status: 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "Mutex konnte nicht freigegeben werden. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" -msgstr "Gerätename konnte nicht gesetzt werden, Status: 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Kann advertisement nicht starten. Status: 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "Verbindung konnte nicht hergestellt werden. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" -msgstr "Starten des Koppelns fehlgeschlagen, Status: 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Der Scanvorgang kann nicht gestartet werden. Status: 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Kann advertisement nicht stoppen. Status: 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1002,9 +1001,8 @@ msgstr "Kein Speicherplatz mehr verfügbar auf dem Gerät" msgid "No such file/directory" msgstr "Keine solche Datei/Verzeichnis" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "Nicht verbunden" @@ -1033,7 +1031,8 @@ msgstr "Nur 8 oder 16 bit mono mit " msgid "" "Only Windows format, uncompressed BMP supported: given header size is %d" msgstr "" -"Nur Windows-Format, unkomprimiertes BMP unterstützt: die gegebene Header-Größe ist %d" +"Nur Windows-Format, unkomprimiertes BMP unterstützt: die gegebene Header-" +"Größe ist %d" #: shared-module/displayio/OnDiskBitmap.c #, c-format @@ -1041,8 +1040,8 @@ msgid "" "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " "%d bpp given" msgstr "" -"Nur monochrome, indizierte 4bpp oder 8bpp, und 16bpp oder größere BMPs unterstützt: " -"%d bpp wurden gegeben" +"Nur monochrome, indizierte 4bpp oder 8bpp, und 16bpp oder größere BMPs " +"unterstützt: %d bpp wurden gegeben" #: shared-bindings/_pixelbuf/PixelBuf.c msgid "Only slices with step=1 (aka None) are supported" @@ -1083,6 +1082,10 @@ msgstr "und alle Module im Dateisystem \n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1151,6 +1154,10 @@ msgstr "Abtastrate muss positiv sein" msgid "Sample rate too high. It must be less than %d" msgstr "Abtastrate zu hoch. Wert muss unter %d liegen" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1165,11 +1172,6 @@ msgstr "Slice und Wert (value) haben unterschiedliche Längen." msgid "Slices not supported" msgstr "Slices werden nicht unterstützt" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Splitting mit sub-captures" @@ -1202,8 +1204,8 @@ msgid "" "The `microcontroller` module was used to boot into safe mode. Press reset to " "exit safe mode.\n" msgstr "" -"Das `Mikrocontroller` Modul wurde benutzt, um in den Sicherheitsmodus zu starten. " -"Drücke Reset um den Sicherheitsmodus zu verlassen.\n" +"Das `Mikrocontroller` Modul wurde benutzt, um in den Sicherheitsmodus zu " +"starten. Drücke Reset um den Sicherheitsmodus zu verlassen.\n" #: supervisor/shared/safe_mode.c msgid "" @@ -1740,7 +1742,8 @@ msgstr "Farbpuffer muss ein Puffer oder ein int sein" #: shared-bindings/displayio/Palette.c msgid "color buffer must be a bytearray or array of type 'b' or 'B'" -msgstr "Farbpuffer muss ein Byte-Array oder ein Array vom Typ 'b' oder 'B' sein" +msgstr "" +"Farbpuffer muss ein Byte-Array oder ein Array vom Typ 'b' oder 'B' sein" #: shared-bindings/displayio/Palette.c msgid "color must be between 0x000000 and 0xffffff" @@ -1996,7 +1999,7 @@ msgstr "int() arg 2 muss >= 2 und <= 36 sein" msgid "integer required" msgstr "integer erforderlich" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "Das Intervall muss im Bereich %s-%s sein" @@ -2179,10 +2182,6 @@ msgstr "muss Schlüsselwortargument für key function verwenden" msgid "name '%q' is not defined" msgstr "Name '%q' ist nirgends definiert worden (Schreibweise kontrollieren)" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "name muss ein String sein" - #: py/runtime.c msgid "name not defined" msgstr "Dieser Name ist nirgends definiert worden (Schreibweise kontrollieren)" @@ -2233,7 +2232,7 @@ msgstr "kein Reset Pin verfügbar" msgid "no such attribute" msgstr "kein solches Attribut" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2724,7 +2723,7 @@ msgstr "Wert muss in %d Byte(s) passen" msgid "value_count must be > 0" msgstr "value_count muss größer als 0 sein" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2811,18 +2810,36 @@ msgstr "" #~ msgid "Error in ffi_prep_cif" #~ msgstr "Fehler in ffi_prep_cif" +#~ msgid "Expected a Peripheral" +#~ msgstr "Ein Peripheriegerät wird erwartet" + #~ msgid "Failed to acquire mutex" #~ msgstr "Akquirieren des Mutex gescheitert" +#, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Hinzufügen des Characteristic ist gescheitert. Status: 0x%04x" + #~ msgid "Failed to add service" #~ msgstr "Dienst konnte nicht hinzugefügt werden" +#, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Dienst konnte nicht hinzugefügt werden. Status: 0x%04x" + +#~ msgid "Failed to change softdevice state" +#~ msgstr "Fehler beim Ändern des Softdevice-Status" + #~ msgid "Failed to connect:" #~ msgstr "Verbindung fehlgeschlagen:" #~ msgid "Failed to continue scanning" #~ msgstr "Der Scanvorgang kann nicht fortgesetzt werden" +#, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Der Scanvorgang kann nicht fortgesetzt werden. Status: 0x%04x" + #~ msgid "Failed to create mutex" #~ msgstr "Erstellen des Mutex ist fehlgeschlagen" @@ -2835,15 +2852,31 @@ msgstr "" #~ msgid "Failed to release mutex" #~ msgstr "Loslassen des Mutex gescheitert" +#, c-format +#~ msgid "Failed to set device name, err 0x%04x" +#~ msgstr "Gerätename konnte nicht gesetzt werden, Status: 0x%04x" + #~ msgid "Failed to start advertising" #~ msgstr "Kann advertisement nicht starten" +#, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Kann advertisement nicht starten. Status: 0x%04x" + +#, c-format +#~ msgid "Failed to start pairing, error 0x%04x" +#~ msgstr "Starten des Koppelns fehlgeschlagen, Status: 0x%04x" + #~ msgid "Failed to start scanning" #~ msgstr "Der Scanvorgang kann nicht gestartet werden" #~ msgid "Failed to stop advertising" #~ msgstr "Kann advertisement nicht stoppen" +#, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Kann advertisement nicht stoppen. Status: 0x%04x" + #~ msgid "Function requires lock." #~ msgstr "" #~ "Die Funktion erwartet, dass der 'lock'-Befehl zuvor ausgeführt wurde" @@ -2977,6 +3010,9 @@ msgstr "" #~ msgstr "" #~ "Speicherallozierung fehlgeschlagen, alloziere %u Bytes für nativen Code" +#~ msgid "name must be a string" +#~ msgstr "name muss ein String sein" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "Kein gültiger ADC Kanal: %d" diff --git a/locale/en_US.po b/locale/en_US.po index 652053ee99..b30e17cecc 100644 --- a/locale/en_US.po +++ b/locale/en_US.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: \n" @@ -259,6 +259,10 @@ msgstr "" msgid "All timers in use" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "" @@ -325,6 +329,11 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -455,6 +464,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -497,7 +512,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "" @@ -543,10 +558,6 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -556,7 +567,7 @@ msgstr "" msgid "Expected a UUID" msgstr "" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -565,6 +576,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -575,8 +591,7 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -584,11 +599,6 @@ msgstr "" msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "" @@ -600,24 +610,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "" @@ -634,7 +642,7 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -643,8 +651,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -664,34 +671,26 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -989,9 +988,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1065,6 +1063,10 @@ msgstr "" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1131,6 +1133,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1145,11 +1151,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "" @@ -1950,7 +1951,7 @@ msgstr "" msgid "integer required" msgstr "" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2127,10 +2128,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "" - #: py/runtime.c msgid "name not defined" msgstr "" @@ -2181,7 +2178,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2663,7 +2660,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po index 1d2fcb659c..f9bb0a4002 100644 --- a/locale/en_x_pirate.po +++ b/locale/en_x_pirate.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: @sommersoft, @MrCertainly\n" @@ -261,6 +261,10 @@ msgstr "" msgid "All timers in use" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "" @@ -329,6 +333,11 @@ msgstr "" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -459,6 +468,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -501,7 +516,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "" @@ -547,10 +562,6 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -560,7 +571,7 @@ msgstr "" msgid "Expected a UUID" msgstr "" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -569,6 +580,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -579,8 +595,7 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -588,11 +603,6 @@ msgstr "" msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "" @@ -604,24 +614,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "" @@ -638,7 +646,7 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -647,8 +655,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -668,34 +675,26 @@ msgstr "" msgid "Failed to release mutex, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c @@ -993,9 +992,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1069,6 +1067,10 @@ msgstr "" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1135,6 +1137,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1149,11 +1155,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "" @@ -1954,7 +1955,7 @@ msgstr "" msgid "integer required" msgstr "" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2131,10 +2132,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "" - #: py/runtime.c msgid "name not defined" msgstr "" @@ -2185,7 +2182,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2667,7 +2664,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" diff --git a/locale/es.po b/locale/es.po index ca8593dcdf..8bcfcedbe3 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-08-24 22:56-0500\n" "Last-Translator: \n" "Language-Team: \n" @@ -263,6 +263,10 @@ msgstr "Todos los timers para este pin están siendo utilizados" msgid "All timers in use" msgstr "Todos los timers en uso" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Funcionalidad AnalogOut no soportada" @@ -333,6 +337,11 @@ msgstr "El brillo debe estar entro 0 y 255" msgid "Brightness not adjustable" msgstr "El brillo no se puede ajustar" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -463,6 +472,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "Command debe estar entre 0 y 255." +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -505,7 +520,7 @@ msgstr "El pin Data 0 debe estar alineado a bytes" msgid "Data chunk must follow fmt chunk" msgstr "Trozo de datos debe seguir fmt chunk" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Data es muy grande para el paquete de advertisement." @@ -551,10 +566,6 @@ msgstr "Se espera un %q" msgid "Expected a Characteristic" msgstr "Se esperaba una Característica." -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -564,7 +575,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Se esperaba un UUID" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -573,6 +584,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "Se esperaba un tuple de %d, se obtuvo %d" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "Fallo enviando comando" @@ -583,20 +599,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "No se puede adquirir el mutex, status: 0x%08lX" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Fallo al añadir caracteristica, err: 0x%08lX" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Fallo al agregar servicio. err: 0x%02x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Ha fallado la asignación del buffer RX" @@ -608,24 +618,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Falló la asignación del buffer RX de %d bytes" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" -msgstr "No se puede cambiar el estado del softdevice" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "No se puede iniciar el escaneo. err: 0x%02x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "No se puede descubrir servicios" @@ -643,7 +651,7 @@ msgstr "No se puede obtener el estado del softdevice" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Error al notificar o indicar el valor del atributo, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -652,8 +660,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "No se puede leer el valor del atributo. err 0x%02x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, fuzzy, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Error al leer valor del atributo, err 0x%04" @@ -673,35 +680,27 @@ msgstr "Fallo al registrar el Vendor-Specific UUID, err 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "No se puede liberar el mutex, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "No se puede inicar el anuncio. err: 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "No se puede iniciar el escaneo. err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "No se puede detener el anuncio. err: 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1004,9 +1003,8 @@ msgstr "No queda espacio en el dispositivo" msgid "No such file/directory" msgstr "No existe el archivo/directorio" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "No conectado" @@ -1088,6 +1086,10 @@ msgstr "Incapaz de montar de nuevo el sistema de archivos" msgid "Pop from an empty Ps2 buffer" msgstr "Pop de un buffer Ps2 vacio" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1157,6 +1159,10 @@ msgstr "Sample rate debe ser positivo" msgid "Sample rate too high. It must be less than %d" msgstr "Frecuencia de muestreo demasiado alta. Debe ser menor a %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1171,11 +1177,6 @@ msgstr "Slice y value tienen diferentes longitudes" msgid "Slices not supported" msgstr "Rebanadas no soportadas" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Dividiendo con sub-capturas" @@ -2004,7 +2005,7 @@ msgstr "int() arg 2 debe ser >= 2 y <= 36" msgid "integer required" msgstr "Entero requerido" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2184,10 +2185,6 @@ msgstr "debe utilizar argumento de palabra clave para la función clave" msgid "name '%q' is not defined" msgstr "name '%q' no esta definido" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "name debe de ser un string" - #: py/runtime.c msgid "name not defined" msgstr "name no definido" @@ -2238,7 +2235,7 @@ msgstr "" msgid "no such attribute" msgstr "no hay tal atributo" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2728,7 +2725,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2818,10 +2815,21 @@ msgstr "paso cero" #~ msgid "Failed to acquire mutex" #~ msgstr "No se puede adquirir el mutex, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Fallo al añadir caracteristica, err: 0x%08lX" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "No se puede detener el anuncio. status: 0x%02x" +#, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Fallo al agregar servicio. err: 0x%02x" + +#~ msgid "Failed to change softdevice state" +#~ msgstr "No se puede cambiar el estado del softdevice" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "No se puede conectar. status: 0x%02x" @@ -2830,6 +2838,10 @@ msgstr "paso cero" #~ msgid "Failed to continue scanning" #~ msgstr "No se puede iniciar el escaneo. status: 0x%02x" +#, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "No se puede iniciar el escaneo. err: 0x%02x" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "No se puede leer el valor del atributo. status 0x%02x" @@ -2850,6 +2862,10 @@ msgstr "paso cero" #~ msgid "Failed to start advertising" #~ msgstr "No se puede inicar el anuncio. status: 0x%02x" +#, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "No se puede inicar el anuncio. err: 0x%04x" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "No se puede iniciar el escaneo. status: 0x%02x" @@ -2858,6 +2874,10 @@ msgstr "paso cero" #~ msgid "Failed to stop advertising" #~ msgstr "No se puede detener el anuncio. status: 0x%02x" +#, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "No se puede detener el anuncio. err: 0x%04x" + #~ msgid "Function requires lock." #~ msgstr "La función requiere lock" @@ -2932,6 +2952,10 @@ msgstr "paso cero" #~ msgid "STA required" #~ msgstr "STA requerido" +#, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX" + #~ msgid "Tile indices must be 0 - 255" #~ msgstr "Los índices de Tile deben ser 0 - 255" @@ -3027,6 +3051,9 @@ msgstr "paso cero" #~ msgstr "" #~ "falló la asignación de memoria, asignando %u bytes para código nativo" +#~ msgid "name must be a string" +#~ msgstr "name debe de ser un string" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "no es un canal ADC válido: %d" diff --git a/locale/fil.po b/locale/fil.po index 6f460c94cf..2223ee7793 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-12-20 22:15-0800\n" "Last-Translator: Timothy \n" "Language-Team: fil\n" @@ -263,6 +263,10 @@ msgstr "Lahat ng timers para sa pin na ito ay ginagamit" msgid "All timers in use" msgstr "Lahat ng timer ginagamit" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Hindi supportado ang AnalogOut" @@ -331,6 +335,11 @@ msgstr "Ang liwanag ay dapat sa gitna ng 0 o 255" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -464,6 +473,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "Sa gitna ng 0 o 255 dapat ang bytes." +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -507,7 +522,7 @@ msgstr "graphic ay dapat 2048 bytes ang haba" msgid "Data chunk must follow fmt chunk" msgstr "Dapat sunurin ng Data chunk ang fmt chunk" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy msgid "Data too large for advertisement packet" msgstr "Hindi makasya ang data sa loob ng advertisement packet" @@ -556,10 +571,6 @@ msgstr "Umasa ng %q" msgid "Expected a Characteristic" msgstr "Hindi mabasa and Characteristic." -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -570,7 +581,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Umasa ng %q" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -579,6 +590,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -589,20 +605,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Nabigo sa pag kuha ng mutex, status: 0x%08lX" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Nabigo sa paglagay ng characteristic, status: 0x%08lX" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Hindi matagumpay ang paglagay ng service, status: 0x%08lX" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Nabigong ilaan ang RX buffer" @@ -614,25 +624,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Nabigong ilaan ang RX buffer ng %d bytes" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Nabigo sa pagbago ng softdevice state, error: 0x%08lX" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Nabigo sa pagdiscover ng services, status: 0x%08lX" @@ -652,7 +659,7 @@ msgstr "Nabigo sa pagkuha ng softdevice state, error: 0x%08lX" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -661,8 +668,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Hindi mabasa ang value ng attribute, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -682,35 +688,27 @@ msgstr "Hindi matagumpay ang paglagay ng Vender Specific UUID, status: 0x%08lX" msgid "Failed to release mutex, err 0x%04x" msgstr "Nabigo sa pagrelease ng mutex, status: 0x%08lX" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Hindi masimulaan mag i-scan, status: 0x%0xlX" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Hindi mahinto ang advertisement, status: 0x%08lX" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1013,9 +1011,8 @@ msgstr "" msgid "No such file/directory" msgstr "Walang file/directory" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Hindi maka connect sa AP" @@ -1094,6 +1091,10 @@ msgstr "Kasama ang kung ano pang modules na sa filesystem\n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1164,6 +1165,10 @@ msgstr "Sample rate ay dapat positibo" msgid "Sample rate too high. It must be less than %d" msgstr "Sample rate ay masyadong mataas. Ito ay dapat hindi hiigit sa %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1178,11 +1183,6 @@ msgstr "Slice at value iba't ibang haba." msgid "Slices not supported" msgstr "Hindi suportado ang Slices" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Binibiyak gamit ang sub-captures" @@ -2016,7 +2016,7 @@ msgstr "int() arg 2 ay dapat >=2 at <= 36" msgid "integer required" msgstr "kailangan ng int" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2197,11 +2197,6 @@ msgstr "dapat gumamit ng keyword argument para sa key function" msgid "name '%q' is not defined" msgstr "name '%q' ay hindi defined" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "ang keywords dapat strings" - #: py/runtime.c msgid "name not defined" msgstr "name hindi na define" @@ -2252,7 +2247,7 @@ msgstr "" msgid "no such attribute" msgstr "walang ganoon na attribute" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2741,7 +2736,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2825,10 +2820,22 @@ msgstr "zero step" #~ msgid "Failed to acquire mutex" #~ msgstr "Nabigo sa pag kuha ng mutex, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Nabigo sa paglagay ng characteristic, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Hindi matagumpay ang paglagay ng service, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Hindi matagumpay ang paglagay ng service, status: 0x%08lX" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Nabigo sa pagbago ng softdevice state, error: 0x%08lX" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "Hindi makaconnect, status: 0x%08lX" @@ -2837,6 +2844,10 @@ msgstr "zero step" #~ msgid "Failed to continue scanning" #~ msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX" +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Hindi matagumpay ang pagbuo ng mutex, status: 0x%0xlX" @@ -2857,6 +2868,10 @@ msgstr "zero step" #~ msgid "Failed to start advertising" #~ msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Hindi masimulaan mag i-scan, status: 0x%0xlX" @@ -2865,6 +2880,10 @@ msgstr "zero step" #~ msgid "Failed to stop advertising" #~ msgstr "Hindi mahinto ang advertisement, status: 0x%08lX" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Hindi mahinto ang advertisement, status: 0x%08lX" + #~ msgid "Function requires lock." #~ msgstr "Kailangan ng lock ang function." @@ -3010,6 +3029,10 @@ msgstr "zero step" #~ msgstr "" #~ "nabigo ang paglalaan ng memorya, naglalaan ng %u bytes para sa native code" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "ang keywords dapat strings" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "hindi tamang ADC Channel: %d" diff --git a/locale/fr.po b/locale/fr.po index c176fd8bcf..9136376758 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2019-04-14 20:05+0100\n" "Last-Translator: Pierrick Couturier \n" "Language-Team: fr\n" @@ -266,6 +266,10 @@ msgstr "Tous les timers pour cette broche sont utilisés" msgid "All timers in use" msgstr "Tous les timers sont utilisés" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Fonctionnalité AnalogOut non supportée" @@ -336,6 +340,11 @@ msgstr "La luminosité doit être entre 0 et 255" msgid "Brightness not adjustable" msgstr "Luminosité non-ajustable" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -470,6 +479,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "La commande doit être un entier entre 0 et 255" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -513,7 +528,7 @@ msgstr "La broche 'Data 0' doit être aligné sur l'octet" msgid "Data chunk must follow fmt chunk" msgstr "Un bloc de données doit suivre un bloc de format" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Données trop volumineuses pour un paquet de diffusion" @@ -560,10 +575,6 @@ msgstr "Attendu un %q" msgid "Expected a Characteristic" msgstr "Une 'Characteristic' est attendue" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -574,7 +585,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Un UUID est attendu" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -583,6 +594,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "Tuple de longueur %d attendu, obtenu %d" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -593,20 +609,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Echec de l'obtention de mutex, err 0x%04x" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Echec de l'ajout de caractéristique, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Echec de l'ajout de service, err 0x%04x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Echec de l'allocation du tampon RX" @@ -618,25 +628,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Echec de l'allocation de %d octets du tampon RX" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Echec de la modification de l'état du périphérique" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Impossible de poursuivre le scan, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Echec de la découverte de services" @@ -657,7 +664,7 @@ msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" "Impossible de notifier ou d'indiquer la valeur de l'attribut, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -666,8 +673,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Impossible de lire la valeur 'CCCD', err 0x%04x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Impossible de lire la valeur de l'attribut, err 0x%04x" @@ -687,35 +693,27 @@ msgstr "Echec de l'ajout de l'UUID du fournisseur, err 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "Impossible de libérer mutex, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Impossible de commencer à diffuser, err 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Impossible de commencer à scanner, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Echec de l'arrêt de diffusion, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1022,9 +1020,8 @@ msgstr "Il n'y a plus d'espace libre sur le périphérique" msgid "No such file/directory" msgstr "Fichier/dossier introuvable" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Non connecté" @@ -1111,6 +1108,10 @@ msgstr "Ainsi que tout autre module présent sur le système de fichiers\n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "Appuyez sur une touche pour entrer sur REPL ou CTRL-D pour recharger." @@ -1180,6 +1181,10 @@ msgstr "Le taux d'échantillonage doit être positif" msgid "Sample rate too high. It must be less than %d" msgstr "Taux d'échantillonage trop élevé. Doit être inf. à %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1194,11 +1199,6 @@ msgstr "Tranche et valeur de tailles différentes" msgid "Slices not supported" msgstr "Tranches non supportées" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Assertion en mode 'soft-device', id: 0x%08lX, pc: 0x%08lX" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Fractionnement avec des sous-captures" @@ -2048,7 +2048,7 @@ msgstr "l'argument 2 de int() doit être >=2 et <=36" msgid "integer required" msgstr "entier requis" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2229,11 +2229,6 @@ msgstr "doit utiliser un argument nommé pour une fonction key" msgid "name '%q' is not defined" msgstr "nom '%q' non défini" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "les noms doivent être des chaînes de caractère" - #: py/runtime.c msgid "name not defined" msgstr "nom non défini" @@ -2285,7 +2280,7 @@ msgstr "" msgid "no such attribute" msgstr "pas de tel attribut" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2783,7 +2778,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "'value_count' doit être > 0" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2873,10 +2868,22 @@ msgstr "'step' nul" #~ msgid "Failed to acquire mutex" #~ msgstr "Echec de l'obtention de mutex" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Echec de l'ajout de caractéristique, err 0x%04x" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Echec de l'ajout de service" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Echec de l'ajout de service, err 0x%04x" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Echec de la modification de l'état du périphérique" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "Echec de connection:" @@ -2885,6 +2892,10 @@ msgstr "'step' nul" #~ msgid "Failed to continue scanning" #~ msgstr "Impossible de poursuivre le scan" +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Impossible de poursuivre le scan, err 0x%04x" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Echec de la création de mutex" @@ -2905,6 +2916,10 @@ msgstr "'step' nul" #~ msgid "Failed to start advertising" #~ msgstr "Echec du démarrage de la diffusion" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Impossible de commencer à diffuser, err 0x%04x" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Impossible de commencer à scanner" @@ -2913,6 +2928,10 @@ msgstr "'step' nul" #~ msgid "Failed to stop advertising" #~ msgstr "Echec de l'arrêt de diffusion" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Echec de l'arrêt de diffusion, err 0x%04x" + #~ msgid "Function requires lock." #~ msgstr "La fonction nécessite un verrou." @@ -2984,6 +3003,10 @@ msgstr "'step' nul" #~ msgid "STA required" #~ msgstr "'STA' requis" +#, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Assertion en mode 'soft-device', id: 0x%08lX, pc: 0x%08lX" + #~ msgid "Tile indices must be 0 - 255" #~ msgstr "Les indices des tuiles doivent être compris entre 0 et 255 " @@ -3077,6 +3100,10 @@ msgstr "'step' nul" #~ msgstr "" #~ "l'allocation de mémoire a échoué en allouant %u octets pour un code natif" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "les noms doivent être des chaînes de caractère" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "canal ADC non valide : %d" diff --git a/locale/it_IT.po b/locale/it_IT.po index 883c65d41f..d4035fdf09 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-10-02 16:27+0200\n" "Last-Translator: Enrico Paganin \n" "Language-Team: \n" @@ -262,6 +262,10 @@ msgstr "Tutti i timer per questo pin sono in uso" msgid "All timers in use" msgstr "Tutti i timer utilizzati" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "funzionalità AnalogOut non supportata" @@ -331,6 +335,11 @@ msgstr "La luminosità deve essere compreso tra 0 e 255" msgid "Brightness not adjustable" msgstr "Illiminazione non è regolabile" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -465,6 +474,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "I byte devono essere compresi tra 0 e 255" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -508,7 +523,7 @@ msgstr "graphic deve essere lunga 2048 byte" msgid "Data chunk must follow fmt chunk" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy msgid "Data too large for advertisement packet" msgstr "Impossibile inserire dati nel pacchetto di advertisement." @@ -556,10 +571,6 @@ msgstr "Atteso un %q" msgid "Expected a Characteristic" msgstr "Non è possibile aggiungere Characteristic." -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -570,7 +581,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Atteso un %q" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -579,6 +590,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -589,20 +605,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Impossibile fermare advertisement. status: 0x%02x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Impossibile fermare advertisement. status: 0x%02x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Impossibile allocare buffer RX" @@ -614,25 +624,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Fallita allocazione del buffer RX di %d byte" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Impossibile fermare advertisement. status: 0x%02x" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Impossible iniziare la scansione. status: 0x%02x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Impossibile fermare advertisement. status: 0x%02x" @@ -651,7 +658,7 @@ msgstr "Impossibile fermare advertisement. status: 0x%02x" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Notificamento o indicazione di attribute value fallito, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -660,8 +667,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Tentative leggere attribute value fallito, err 0x%04x" @@ -681,35 +687,27 @@ msgstr "Non è possibile aggiungere l'UUID del vendor specifico da 128-bit" msgid "Failed to release mutex, err 0x%04x" msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Impossibile avviare advertisement. status: 0x%02x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Impossible iniziare la scansione. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Impossibile fermare advertisement. status: 0x%02x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1012,9 +1010,8 @@ msgstr "Non che spazio sul dispositivo" msgid "No such file/directory" msgstr "Nessun file/directory esistente" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Impossible connettersi all'AP" @@ -1099,6 +1096,10 @@ msgstr "Imposssibile rimontare il filesystem" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1170,6 +1171,10 @@ msgid "Sample rate too high. It must be less than %d" msgstr "" "Frequenza di campionamento troppo alta. Il valore deve essere inferiore a %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1184,11 +1189,6 @@ msgstr "" msgid "Slices not supported" msgstr "Slice non supportate" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Suddivisione con sotto-catture" @@ -2008,7 +2008,7 @@ msgstr "il secondo argomanto di int() deve essere >= 2 e <= 36" msgid "integer required" msgstr "intero richiesto" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2190,11 +2190,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "nome '%q'non definito" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "argomenti nominati devono essere stringhe" - #: py/runtime.c msgid "name not defined" msgstr "nome non definito" @@ -2246,7 +2241,7 @@ msgstr "" msgid "no such attribute" msgstr "attributo inesistente" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2739,7 +2734,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2829,10 +2824,22 @@ msgstr "zero step" #~ msgid "Failed to acquire mutex" #~ msgstr "Impossibile allocare buffer RX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Impossibile fermare advertisement. status: 0x%02x" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Impossibile fermare advertisement. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Impossibile fermare advertisement. status: 0x%02x" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Impossibile fermare advertisement. status: 0x%02x" + #, fuzzy #~ msgid "Failed to connect:" #~ msgstr "Impossibile connettersi. status: 0x%02x" @@ -2841,6 +2848,10 @@ msgstr "zero step" #~ msgid "Failed to continue scanning" #~ msgstr "Impossible iniziare la scansione. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Impossible iniziare la scansione. status: 0x%02x" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" @@ -2861,6 +2872,10 @@ msgstr "zero step" #~ msgid "Failed to start advertising" #~ msgstr "Impossibile avviare advertisement. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Impossibile avviare advertisement. status: 0x%02x" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Impossible iniziare la scansione. status: 0x%02x" @@ -2869,6 +2884,10 @@ msgstr "zero step" #~ msgid "Failed to stop advertising" #~ msgstr "Impossibile fermare advertisement. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Impossibile fermare advertisement. status: 0x%02x" + #~ msgid "GPIO16 does not support pull up." #~ msgstr "GPIO16 non supporta pull-up" @@ -3008,6 +3027,10 @@ msgstr "zero step" #~ msgstr "" #~ "allocazione di memoria fallita, allocazione di %d byte per codice nativo" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "argomenti nominati devono essere stringhe" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "canale ADC non valido: %d" diff --git a/locale/pl.po b/locale/pl.po index 9ed76924b5..0edc5906e8 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2019-03-19 18:37-0700\n" "Last-Translator: Radomir Dopieralski \n" "Language-Team: pl\n" @@ -260,6 +260,10 @@ msgstr "Wszystkie timery tej nóżki w użyciu" msgid "All timers in use" msgstr "Wszystkie timery w użyciu" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "AnalogOut jest niewspierane" @@ -328,6 +332,11 @@ msgstr "Jasność musi być pomiędzy 0 a 255" msgid "Brightness not adjustable" msgstr "Jasność nie jest regulowana" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -458,6 +467,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "Komenda musi być int pomiędzy 0 a 255" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -500,7 +515,7 @@ msgstr "Nóżka data 0 musi być wyrównana do bajtu" msgid "Data chunk must follow fmt chunk" msgstr "Fragment danych musi następować po fragmencie fmt" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Zbyt dużo danych pakietu rozgłoszeniowego" @@ -546,10 +561,6 @@ msgstr "Oczekiwano %q" msgid "Expected a Characteristic" msgstr "Oczekiwano charakterystyki" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -559,7 +570,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Oczekiwano UUID" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -568,6 +579,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "Oczekiwano krotkę długości %d, otrzymano %d" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "" @@ -578,20 +594,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Nie udało się uzyskać blokady, błąd 0x$04x" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Nie udało się dodać charakterystyki, błąd 0x$04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Nie udało się dodać serwisu, błąd 0x%04x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Nie udała się alokacja bufora RX" @@ -603,24 +613,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Nie udała się alokacja %d bajtów na bufor RX" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" -msgstr "Nie udało się zmienić stanu softdevice" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Nie udała się kontynuacja skanowania, błąd 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "Nie udało się odkryć serwisów" @@ -637,7 +645,7 @@ msgstr "Nie udało się odczytać stanu softdevice" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Nie udało się powiadomić o wartości atrybutu, błąd 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -646,8 +654,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Nie udało się odczytać CCCD, błąd 0x%04x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Nie udało się odczytać wartości atrybutu, błąd 0x%04x" @@ -667,35 +674,27 @@ msgstr "Nie udało się zarejestrować UUID dostawcy, błąd 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "Nie udało się zwolnić blokady, błąd 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Nie udało się rozpocząć rozgłaszania, błąd 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Nie udało się rozpocząć skanowania, błąd 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Nie udało się zatrzymać rozgłaszania, błąd 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -999,9 +998,8 @@ msgstr "Brak miejsca" msgid "No such file/directory" msgstr "Brak pliku/katalogu" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "Nie podłączono" @@ -1075,6 +1073,10 @@ msgstr "Oraz moduły w systemie plików\n" msgid "Pop from an empty Ps2 buffer" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "Dowolny klawisz aby uruchomić konsolę. CTRL-D aby przeładować." @@ -1141,6 +1143,10 @@ msgstr "Częstotliwość próbkowania musi być dodatnia" msgid "Sample rate too high. It must be less than %d" msgstr "Zbyt wysoka częstotliwość próbkowania. Musi być mniejsza niż %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1155,11 +1161,6 @@ msgstr "Fragment i wartość są różnych długości." msgid "Slices not supported" msgstr "Fragmenty nieobsługiwane" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Podział z podgrupami" @@ -1975,7 +1976,7 @@ msgstr "argument 2 do int() busi być pomiędzy 2 a 36" msgid "integer required" msgstr "wymagana liczba całkowita" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2152,10 +2153,6 @@ msgstr "funkcja key musi być podana jako argument nazwany" msgid "name '%q' is not defined" msgstr "nazwa '%q' niezdefiniowana" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "nazwa musi być łańcuchem" - #: py/runtime.c msgid "name not defined" msgstr "nazwa niezdefiniowana" @@ -2206,7 +2203,7 @@ msgstr "" msgid "no such attribute" msgstr "nie ma takiego atrybutu" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2690,7 +2687,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "value_count musi być > 0" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2749,15 +2746,30 @@ msgstr "zerowy krok" #~ msgid "Failed to acquire mutex" #~ msgstr "Nie udało się uzyskać blokady" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Nie udało się dodać charakterystyki, błąd 0x$04x" + #~ msgid "Failed to add service" #~ msgstr "Nie udało się dodać serwisu" +#, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Nie udało się dodać serwisu, błąd 0x%04x" + +#~ msgid "Failed to change softdevice state" +#~ msgstr "Nie udało się zmienić stanu softdevice" + #~ msgid "Failed to connect:" #~ msgstr "Nie udało się połączenie:" #~ msgid "Failed to continue scanning" #~ msgstr "Nie udała się kontynuacja skanowania" +#, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Nie udała się kontynuacja skanowania, błąd 0x%04x" + #~ msgid "Failed to create mutex" #~ msgstr "Nie udało się stworzyć blokady" @@ -2767,12 +2779,20 @@ msgstr "zerowy krok" #~ msgid "Failed to start advertising" #~ msgstr "Nie udało się rozpocząć rozgłaszania" +#, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Nie udało się rozpocząć rozgłaszania, błąd 0x%04x" + #~ msgid "Failed to start scanning" #~ msgstr "Nie udało się rozpocząć skanowania" #~ msgid "Failed to stop advertising" #~ msgstr "Nie udało się zatrzymać rozgłaszania" +#, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Nie udało się zatrzymać rozgłaszania, błąd 0x%04x" + #~ msgid "Invalid bit clock pin" #~ msgstr "Zła nóżka zegara" @@ -2790,6 +2810,10 @@ msgstr "zerowy krok" #~ "bpp given" #~ msgstr "Wspierane są tylko pliki BMP czarno-białe, 8bpp i 16bpp: %d bpp " +#, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Soft device assert, id: 0x%08lX, pc: 0x%08lX" + #~ msgid "Tile indices must be 0 - 255" #~ msgstr "Indeks kafelka musi być pomiędzy 0 a 255 włącznie" @@ -2809,6 +2833,9 @@ msgstr "zerowy krok" #~ msgid "interval not in range 0.0020 to 10.24" #~ msgstr "przedział poza zakresem 0.0020 do 10.24" +#~ msgid "name must be a string" +#~ msgstr "nazwa musi być łańcuchem" + #~ msgid "services includes an object that is not a Service" #~ msgstr "obiekt typu innego niż Service w services" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index a17a275390..b5cd24405a 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2018-10-02 21:14-0000\n" "Last-Translator: \n" "Language-Team: \n" @@ -262,6 +262,10 @@ msgstr "Todos os temporizadores para este pino estão em uso" msgid "All timers in use" msgstr "Todos os temporizadores em uso" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Funcionalidade AnalogOut não suportada" @@ -328,6 +332,11 @@ msgstr "O brilho deve estar entre 0 e 255" msgid "Brightness not adjustable" msgstr "" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -461,6 +470,12 @@ msgstr "" msgid "Command must be an int between 0 and 255" msgstr "Os bytes devem estar entre 0 e 255." +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -503,7 +518,7 @@ msgstr "" msgid "Data chunk must follow fmt chunk" msgstr "Pedaço de dados deve seguir o pedaço de cortes" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy msgid "Data too large for advertisement packet" msgstr "Não é possível ajustar dados no pacote de anúncios." @@ -551,10 +566,6 @@ msgstr "Esperado um" msgid "Expected a Characteristic" msgstr "Não é possível adicionar Característica." -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" @@ -565,7 +576,7 @@ msgstr "" msgid "Expected a UUID" msgstr "Esperado um" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "" @@ -574,6 +585,11 @@ msgstr "" msgid "Expected tuple of length %d, got %d" msgstr "" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "Falha ao enviar comando." @@ -584,20 +600,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Não é possível ler o valor do atributo. status: 0x%02x" #: ports/nrf/common-hal/_bleio/Service.c -#, fuzzy, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Não pode parar propaganda. status: 0x%02x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Não pode parar propaganda. status: 0x%02x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Falha ao alocar buffer RX" @@ -609,25 +619,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Falha ao alocar buffer RX de %d bytes" #: ports/nrf/common-hal/_bleio/Adapter.c -#, fuzzy -msgid "Failed to change softdevice state" -msgstr "Não pode parar propaganda. status: 0x%02x" - -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" +msgid "Failed to change softdevice state, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" + +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, fuzzy, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Não é possível iniciar o anúncio. status: 0x%02x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c #, fuzzy msgid "Failed to discover services" msgstr "Não pode parar propaganda. status: 0x%02x" @@ -646,7 +653,7 @@ msgstr "Não pode parar propaganda. status: 0x%02x" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "" @@ -655,8 +662,7 @@ msgstr "" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Não é possível ler o valor do atributo. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" @@ -676,35 +682,27 @@ msgstr "Não é possível adicionar o UUID de 128 bits específico do fornecedor msgid "Failed to release mutex, err 0x%04x" msgstr "Não é possível ler o valor do atributo. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Não é possível iniciar o anúncio. status: 0x%02x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Não é possível iniciar o anúncio. status: 0x%02x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, fuzzy, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Não pode parar propaganda. status: 0x%02x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -1004,9 +1002,8 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Não é possível conectar-se ao AP" @@ -1084,6 +1081,10 @@ msgstr "Não é possível remontar o sistema de arquivos" msgid "Pop from an empty Ps2 buffer" msgstr "Buffer Ps2 vazio" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" @@ -1151,6 +1152,10 @@ msgstr "" msgid "Sample rate too high. It must be less than %d" msgstr "Taxa de amostragem muito alta. Deve ser menor que %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1165,11 +1170,6 @@ msgstr "" msgid "Slices not supported" msgstr "" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "" @@ -1975,7 +1975,7 @@ msgstr "" msgid "integer required" msgstr "inteiro requerido" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "" @@ -2152,11 +2152,6 @@ msgstr "" msgid "name '%q' is not defined" msgstr "" -#: shared-bindings/_bleio/Peripheral.c -#, fuzzy -msgid "name must be a string" -msgstr "heap deve ser uma lista" - #: py/runtime.c msgid "name not defined" msgstr "nome não definido" @@ -2207,7 +2202,7 @@ msgstr "" msgid "no such attribute" msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "" @@ -2692,7 +2687,7 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "" @@ -2759,10 +2754,26 @@ msgstr "passo zero" #~ msgid "Failed to acquire mutex" #~ msgstr "Falha ao alocar buffer RX" +#, fuzzy, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Não pode parar propaganda. status: 0x%02x" + #, fuzzy #~ msgid "Failed to add service" #~ msgstr "Não pode parar propaganda. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Não pode parar propaganda. status: 0x%02x" + +#, fuzzy +#~ msgid "Failed to change softdevice state" +#~ msgstr "Não pode parar propaganda. status: 0x%02x" + +#, fuzzy, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" + #, fuzzy #~ msgid "Failed to create mutex" #~ msgstr "Não é possível ler o valor do atributo. status: 0x%02x" @@ -2783,6 +2794,10 @@ msgstr "passo zero" #~ msgid "Failed to start advertising" #~ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" + #, fuzzy #~ msgid "Failed to start scanning" #~ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" @@ -2791,6 +2806,10 @@ msgstr "passo zero" #~ msgid "Failed to stop advertising" #~ msgstr "Não pode parar propaganda. status: 0x%02x" +#, fuzzy, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Não pode parar propaganda. status: 0x%02x" + #~ msgid "GPIO16 does not support pull up." #~ msgstr "GPIO16 não suporta pull up." @@ -2921,6 +2940,10 @@ msgstr "passo zero" #~ msgid "memory allocation failed, allocating %u bytes for native code" #~ msgstr "alocação de memória falhou, alocando %u bytes para código nativo" +#, fuzzy +#~ msgid "name must be a string" +#~ msgstr "heap deve ser uma lista" + #~ msgid "not a valid ADC Channel: %d" #~ msgstr "não é um canal ADC válido: %d" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index d5df0b7b0c..dfd7e8b0db 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-08 17:30-0500\n" +"POT-Creation-Date: 2019-10-21 19:50-0700\n" "PO-Revision-Date: 2019-04-13 10:10-0700\n" "Last-Translator: hexthat\n" "Language-Team: Chinese Hanyu Pinyin\n" @@ -261,6 +261,10 @@ msgstr "Cǐ yǐn jiǎo de suǒyǒu jìshí qì zhèngzài shǐyòng" msgid "All timers in use" msgstr "Suǒyǒu jìshí qì shǐyòng" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Already advertising." +msgstr "" + #: ports/nrf/common-hal/analogio/AnalogOut.c msgid "AnalogOut functionality not supported" msgstr "Bù zhīchí AnalogOut gōngnéng" @@ -329,6 +333,11 @@ msgstr "Liàngdù bìxū jiè yú 0 dào 255 zhī jiān" msgid "Brightness not adjustable" msgstr "Liàngdù wúfǎ tiáozhěng" +#: shared-bindings/_bleio/UUID.c +#, c-format +msgid "Buffer + offset too small %d %d %d" +msgstr "" + #: shared-module/usb_hid/Device.c #, c-format msgid "Buffer incorrect size. Should be %d bytes." @@ -459,6 +468,12 @@ msgstr "Mìnglìng bìxū wèi 0-255" msgid "Command must be an int between 0 and 255" msgstr "Mìnglìng bìxū shì 0 dào 255 zhī jiān de int" +#: shared-bindings/_bleio/Connection.c +msgid "" +"Connection has been disconnected and can no longer be used. Create a new " +"connection." +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Fǔbài de .mpy wénjiàn" @@ -501,7 +516,7 @@ msgstr "Shùjù 0 de yǐn jiǎo bìxū shì zì jié duìqí" msgid "Data chunk must follow fmt chunk" msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" msgstr "Guǎnggào bāo de shùjù tài dà" @@ -547,10 +562,6 @@ msgstr "Yùqí %q" msgid "Expected a Characteristic" msgstr "Yùqí de tèdiǎn" -#: shared-bindings/_bleio/Service.c -msgid "Expected a Peripheral" -msgstr "Qídài yīgè wàiwéi shèbèi" - #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Yùqí fúwù" @@ -560,7 +571,7 @@ msgstr "Yùqí fúwù" msgid "Expected a UUID" msgstr "Yùqí UUID" -#: shared-bindings/_bleio/Central.c +#: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" msgstr "Qídài yīgè dìzhǐ" @@ -569,6 +580,11 @@ msgstr "Qídài yīgè dìzhǐ" msgid "Expected tuple of length %d, got %d" msgstr "Qīwàng de chángdù wèi %d de yuán zǔ, dédào %d" +#: ports/nrf/common-hal/_bleio/__init__.c +#, c-format +msgid "Failed initiate attribute read, err 0x%04x" +msgstr "" + #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." msgstr "Fāsòng mìnglìng shībài." @@ -579,20 +595,14 @@ msgid "Failed to acquire mutex, err 0x%04x" msgstr "Wúfǎ huòdé mutex, err 0x%04x" #: ports/nrf/common-hal/_bleio/Service.c -#, c-format -msgid "Failed to add characteristic, err 0x%04x" -msgstr "Tiānjiā tèxìng shībài, err 0x%04x" +msgid "Failed to add characteristic, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format msgid "Failed to add descriptor, err 0x%04x" msgstr "Wúfǎ tiānjiā miáoshù fú, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to add service, err 0x%04x" -msgstr "Tiānjiā fúwù shībài, err 0x%04x" - #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "Failed to allocate RX buffer" msgstr "Fēnpèi RX huǎnchōng shībài" @@ -604,24 +614,22 @@ msgid "Failed to allocate RX buffer of %d bytes" msgstr "Fēnpèi RX huǎnchōng qū%d zì jié shībài" #: ports/nrf/common-hal/_bleio/Adapter.c -msgid "Failed to change softdevice state" -msgstr "Gēnggǎi ruǎn shèbèi zhuàngtài shībài" +msgid "Failed to change softdevice state, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to configure advertising, err 0x%04x" -msgstr "Wúfǎ pèizhì guǎnggào, cuòwù 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to connect: internal error" +msgstr "" -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Liánjiē shībài: Chāoshí" -#: ports/nrf/common-hal/_bleio/Scanner.c -#, c-format -msgid "Failed to continue scanning, err 0x%04x" -msgstr "Jìxù sǎomiáo shībài, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Service.c +msgid "Failed to create service, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to discover services" msgstr "Fāxiàn fúwù shībài" @@ -638,7 +646,7 @@ msgstr "Wúfǎ huòdé ruǎnjiàn shèbèi zhuàngtài" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Wúfǎ tōngzhī huò xiǎnshì shǔxìng zhí, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "Failed to pair" msgstr "Pèiduì shībài" @@ -647,8 +655,7 @@ msgstr "Pèiduì shībài" msgid "Failed to read CCCD value, err 0x%04x" msgstr "Dòu qǔ CCCD zhí, err 0x%04x shībài" -#: ports/nrf/common-hal/_bleio/Characteristic.c -#: ports/nrf/common-hal/_bleio/Descriptor.c +#: ports/nrf/common-hal/_bleio/__init__.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Dòu qǔ shǔxìng zhí shībài, err 0x%04x" @@ -668,35 +675,27 @@ msgstr "Wúfǎ zhùcè màizhǔ tèdìng de UUID, err 0x%04x" msgid "Failed to release mutex, err 0x%04x" msgstr "Wúfǎ shìfàng mutex, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to set device name, err 0x%04x" -msgstr "Wúfǎ shèzhì shèbèi míngchēng, cuòwù 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to start advertising, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start advertising, err 0x%04x" -msgstr "Qǐdòng guǎnggào shībài, err 0x%04x" - -#: ports/nrf/common-hal/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start connecting, error 0x%04x" msgstr "Wúfǎ kāishǐ liánjiē, cuòwù 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to start pairing, error 0x%04x" -msgstr "Wúfǎ kāishǐ pèiduì, cuòwù 0x%04x" +#: ports/nrf/common-hal/_bleio/Connection.c +msgid "Failed to start pairing, NRF_ERROR_%q" +msgstr "" -#: ports/nrf/common-hal/_bleio/Scanner.c +#: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Failed to start scanning, err 0x%04x" msgstr "Qǐdòng sǎomiáo shībài, err 0x%04x" -#: ports/nrf/common-hal/_bleio/Peripheral.c -#, c-format -msgid "Failed to stop advertising, err 0x%04x" -msgstr "Wúfǎ tíngzhǐ guǎnggào, err 0x%04x" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Failed to stop advertising, NRF_ERROR_%q" +msgstr "" #: ports/nrf/common-hal/_bleio/Characteristic.c #, c-format @@ -999,9 +998,8 @@ msgstr "Shèbèi shàng méiyǒu kònggé" msgid "No such file/directory" msgstr "Méiyǒu cǐ lèi wénjiàn/mùlù" -#: ports/nrf/common-hal/_bleio/__init__.c shared-bindings/_bleio/Central.c +#: ports/nrf/common-hal/_bleio/__init__.c #: shared-bindings/_bleio/CharacteristicBuffer.c -#: shared-bindings/_bleio/Peripheral.c msgid "Not connected" msgstr "Wèi liánjiē" @@ -1079,6 +1077,10 @@ msgstr "Zài wénjiàn xìtǒng shàng tiānjiā rènhé mókuài\n" msgid "Pop from an empty Ps2 buffer" msgstr "Cóng kōng de Ps2 huǎnchōng qū dànchū" +#: shared-bindings/_bleio/Adapter.c +msgid "Prefix buffer must be on the heap" +msgstr "" + #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "Àn xià rènhé jiàn jìnrù REPL. Shǐyòng CTRL-D chóngxīn jiāzài." @@ -1145,6 +1147,10 @@ msgstr "Cǎiyàng lǜ bìxū wèi zhèng shù" msgid "Sample rate too high. It must be less than %d" msgstr "Cǎiyàng lǜ tài gāo. Tā bìxū xiǎoyú %d" +#: ports/nrf/common-hal/_bleio/Adapter.c +msgid "Scan already in progess. Stop with stop_scan." +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" @@ -1159,11 +1165,6 @@ msgstr "Qiēpiàn hé zhí bùtóng chángdù." msgid "Slices not supported" msgstr "Qiēpiàn bù shòu zhīchí" -#: ports/nrf/common-hal/_bleio/Adapter.c -#, c-format -msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" -msgstr "Ruǎn shèbèi wéihù, id: 0X%08lX, pc: 0X%08lX" - #: extmod/modure.c msgid "Splitting with sub-captures" msgstr "Yǔ zi bǔhuò fēnliè" @@ -1986,7 +1987,7 @@ msgstr "zhěngshù() cānshù 2 bìxū > = 2 qiě <= 36" msgid "integer required" msgstr "xūyào zhěngshù" -#: shared-bindings/_bleio/Peripheral.c shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" msgstr "Jiàngé bìxū zài %s-%s fànwéi nèi" @@ -2164,10 +2165,6 @@ msgstr "bìxū shǐyòng guānjiàn cí cānshù" msgid "name '%q' is not defined" msgstr "míngchēng '%q' wèi dìngyì" -#: shared-bindings/_bleio/Peripheral.c -msgid "name must be a string" -msgstr "míngchēng bìxū shì yīgè zìfú chuàn" - #: py/runtime.c msgid "name not defined" msgstr "míngchēng wèi dìngyì" @@ -2219,7 +2216,7 @@ msgstr "Méiyǒu kěyòng de fùwèi yǐn jiǎo" msgid "no such attribute" msgstr "méiyǒu cǐ shǔxìng" -#: ports/nrf/common-hal/_bleio/__init__.c +#: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" msgstr "Zài service_uuids bái míngdān zhōng zhǎodào fēi UUID" @@ -2703,7 +2700,7 @@ msgstr "Zhí bìxū fúhé %d zì jié" msgid "value_count must be > 0" msgstr "zhí jìshù bìxū wèi > 0" -#: shared-bindings/_bleio/Scanner.c +#: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" msgstr "Chuāngkǒu bìxū shì <= jiàngé" @@ -2762,33 +2759,71 @@ msgstr "líng bù" #~ msgid "Data too large for the advertisement packet" #~ msgstr "Guǎnggào bāo de shùjù tài dà" +#~ msgid "Expected a Peripheral" +#~ msgstr "Qídài yīgè wàiwéi shèbèi" + #~ msgid "Failed to acquire mutex" #~ msgstr "Wúfǎ huòdé mutex" +#, c-format +#~ msgid "Failed to add characteristic, err 0x%04x" +#~ msgstr "Tiānjiā tèxìng shībài, err 0x%04x" + #~ msgid "Failed to add service" #~ msgstr "Tiānjiā fúwù shībài" +#, c-format +#~ msgid "Failed to add service, err 0x%04x" +#~ msgstr "Tiānjiā fúwù shībài, err 0x%04x" + +#~ msgid "Failed to change softdevice state" +#~ msgstr "Gēnggǎi ruǎn shèbèi zhuàngtài shībài" + +#, c-format +#~ msgid "Failed to configure advertising, err 0x%04x" +#~ msgstr "Wúfǎ pèizhì guǎnggào, cuòwù 0x%04x" + #~ msgid "Failed to connect:" #~ msgstr "Liánjiē shībài:" #~ msgid "Failed to continue scanning" #~ msgstr "Jìxù sǎomiáo shībài" +#, c-format +#~ msgid "Failed to continue scanning, err 0x%04x" +#~ msgstr "Jìxù sǎomiáo shībài, err 0x%04x" + #~ msgid "Failed to create mutex" #~ msgstr "Wúfǎ chuàngjiàn hù chì suǒ" #~ msgid "Failed to release mutex" #~ msgstr "Wúfǎ shìfàng mutex" +#, c-format +#~ msgid "Failed to set device name, err 0x%04x" +#~ msgstr "Wúfǎ shèzhì shèbèi míngchēng, cuòwù 0x%04x" + #~ msgid "Failed to start advertising" #~ msgstr "Qǐdòng guǎnggào shībài" +#, c-format +#~ msgid "Failed to start advertising, err 0x%04x" +#~ msgstr "Qǐdòng guǎnggào shībài, err 0x%04x" + +#, c-format +#~ msgid "Failed to start pairing, error 0x%04x" +#~ msgstr "Wúfǎ kāishǐ pèiduì, cuòwù 0x%04x" + #~ msgid "Failed to start scanning" #~ msgstr "Qǐdòng sǎomiáo shībài" #~ msgid "Failed to stop advertising" #~ msgstr "Wúfǎ tíngzhǐ guǎnggào" +#, c-format +#~ msgid "Failed to stop advertising, err 0x%04x" +#~ msgstr "Wúfǎ tíngzhǐ guǎnggào, err 0x%04x" + #~ msgid "Invalid bit clock pin" #~ msgstr "Wúxiào de wèi shízhōng yǐn jiǎo" @@ -2819,6 +2854,10 @@ msgstr "líng bù" #~ msgstr "" #~ "Jǐn zhīchí dān sè, suǒyǐn 8bpp hé 16bpp huò gèng dà de BMP: %d bpp tígōng" +#, c-format +#~ msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +#~ msgstr "Ruǎn shèbèi wéihù, id: 0X%08lX, pc: 0X%08lX" + #~ msgid "Tile indices must be 0 - 255" #~ msgstr "Píng pū zhǐshù bìxū wèi 0 - 255" @@ -2840,6 +2879,9 @@ msgstr "líng bù" #~ msgid "interval not in range 0.0020 to 10.24" #~ msgstr "jùlí 0.0020 Zhì 10.24 Zhī jiān de jiàngé shíjiān" +#~ msgid "name must be a string" +#~ msgstr "míngchēng bìxū shì yīgè zìfú chuàn" + #~ msgid "row must be packed and word aligned" #~ msgstr "xíng bìxū dǎbāo bìngqiě zì duìqí" diff --git a/main.c b/main.c index 8715672ea9..a6c7c05816 100755 --- a/main.c +++ b/main.c @@ -69,6 +69,11 @@ #include "shared-module/board/__init__.h" #endif +#if CIRCUITPY_BLEIO +#include "shared-bindings/_bleio/__init__.h" +#include "supervisor/shared/bluetooth.h" +#endif + void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { @@ -439,6 +444,10 @@ int __attribute__((used)) main(void) { // Start serial and HID after giving boot.py a chance to tweak behavior. serial_init(); + #if CIRCUITPY_BLEIO + supervisor_start_bluetooth(); + #endif + // Boot script is finished, so now go into REPL/main mode. int exit_code = PYEXEC_FORCED_EXIT; bool skip_repl = true; @@ -475,6 +484,10 @@ void gc_collect(void) { displayio_gc_collect(); #endif + #if CIRCUITPY_BLEIO + common_hal_bleio_gc_collect(); + #endif + // This naively collects all object references from an approximate stack // range. gc_collect_root((void**)sp, ((uint32_t)port_stack_get_top() - sp) / sizeof(uint32_t)); diff --git a/ports/atmel-samd/boards/winterbloom_sol/board.c b/ports/atmel-samd/boards/winterbloom_sol/board.c new file mode 100644 index 0000000000..8096b9b8ea --- /dev/null +++ b/ports/atmel-samd/boards/winterbloom_sol/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 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 "boards/board.h" +#include "mpconfigboard.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.h b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.h new file mode 100644 index 0000000000..7e01e228ac --- /dev/null +++ b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.h @@ -0,0 +1,33 @@ +#define MICROPY_HW_BOARD_NAME "Winterbloom Sol" +#define MICROPY_HW_MCU_NAME "samd51j20" + +#define CIRCUITPY_MCU_FAMILY samd51 + +#define MICROPY_HW_LED_STATUS (&pin_PA23) +#define MICROPY_HW_NEOPIXEL (&pin_PB03) + +// These are pins not to reset. +// QSPI Data pins +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) +// QSPI CS, QSPI SCK and NeoPixel pin +#define MICROPY_PORT_B (PORT_PB03 | PORT_PB10 | PORT_PB11) +#define MICROPY_PORT_C (0) +#define MICROPY_PORT_D (0) + +#define AUTORESET_DELAY_MS 500 + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code +#define CIRCUITPY_INTERNAL_NVM_SIZE 8192 + +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_SPI_BUS_SCK (&pin_PA17) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB23) +#define DEFAULT_SPI_BUS_MISO (&pin_PB22) + +// USB is always used internally so skip the pin objects for it. +#define IGNORE_PIN_PA24 1 +#define IGNORE_PIN_PA25 1 diff --git a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk new file mode 100644 index 0000000000..19917898b6 --- /dev/null +++ b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk @@ -0,0 +1,27 @@ +LD_FILE = boards/samd51x20-bootloader-external-flash.ld +# Adafruit +USB_VID = 0x239A +# Allocated for Winterbloom Sol +# https://github.com/adafruit/circuitpython/issues/2217 +USB_PID = 0x8062 +USB_PRODUCT = "Sol" +USB_MANUFACTURER = "Winterbloom" + +CHIP_VARIANT = SAMD51J20A +CHIP_FAMILY = samd51 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = W25Q32JV_IQ +LONGINT_IMPL = MPZ + +# Disable modules that are unusable on this special-purpose board. +CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOIO = 0 +CIRCUITPY_BLEIO = 0 +CIRCUITPY_DISPLAYIO = 0 +CIRCUITPY_GAMEPAD = 0 +CIRCUITPY_I2CSLAVE = 0 +CIRCUITPY_NETWORK = 0 +CIRCUITPY_TOUCHIO = 0 +CIRCUITPY_PS2IO = 0 diff --git a/ports/atmel-samd/boards/winterbloom_sol/pins.c b/ports/atmel-samd/boards/winterbloom_sol/pins.c new file mode 100644 index 0000000000..013542d3ca --- /dev/null +++ b/ports/atmel-samd/boards/winterbloom_sol/pins.c @@ -0,0 +1,15 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB22) }, + { MP_ROM_QSTR(MP_QSTR_DAC_CS), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_G1), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_G2), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_G3), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_G4), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/nrf/background.c b/ports/nrf/background.c index 305f607c5c..629967b3d0 100644 --- a/ports/nrf/background.c +++ b/ports/nrf/background.c @@ -41,6 +41,10 @@ #include "common-hal/audiopwmio/PWMAudioOut.h" #endif +#if CIRCUITPY_BLEIO +#include "supervisor/shared/bluetooth.h" +#endif + static bool running_background_tasks = false; void background_tasks_reset(void) { @@ -62,6 +66,9 @@ void run_background_tasks(void) { i2s_background(); #endif +#if CIRCUITPY_BLEIO + supervisor_bluetooth_background(); +#endif #if CIRCUITPY_DISPLAYIO displayio_background(); diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c index 6b17e7af29..16475e4b3b 100644 --- a/ports/nrf/bluetooth/ble_drv.c +++ b/ports/nrf/bluetooth/ble_drv.c @@ -38,6 +38,8 @@ #include "py/misc.h" #include "py/mpstate.h" +#include "supervisor/shared/bluetooth.h" + nrf_nvic_state_t nrf_nvic_state = { 0 }; // Flag indicating progress of internal flash operation. @@ -52,6 +54,14 @@ void ble_drv_reset() { sd_flash_operation_status = SD_FLASH_OPERATION_DONE; } +void ble_drv_add_event_handler_entry(ble_drv_evt_handler_entry_t* entry, ble_drv_evt_handler_t func, void *param) { + entry->next = MP_STATE_VM(ble_drv_evt_handler_entries); + entry->param = param; + entry->func = func; + + MP_STATE_VM(ble_drv_evt_handler_entries) = entry; +} + void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) { ble_drv_evt_handler_entry_t *it = MP_STATE_VM(ble_drv_evt_handler_entries); while (it != NULL) { @@ -64,11 +74,7 @@ void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) { // Add a new handler to the front of the list ble_drv_evt_handler_entry_t *handler = m_new_ll(ble_drv_evt_handler_entry_t, 1); - handler->next = MP_STATE_VM(ble_drv_evt_handler_entries); - handler->param = param; - handler->func = func; - - MP_STATE_VM(ble_drv_evt_handler_entries) = handler; + ble_drv_add_event_handler_entry(handler, func, param); } void ble_drv_remove_event_handler(ble_drv_evt_handler_t func, void *param) { @@ -127,10 +133,20 @@ void SD_EVT_IRQHandler(void) { break; } + ble_evt_t* event = (ble_evt_t *)m_ble_evt_buf; + + if (supervisor_bluetooth_hook(event)) { + continue; + } + ble_drv_evt_handler_entry_t *it = MP_STATE_VM(ble_drv_evt_handler_entries); + bool done = false; while (it != NULL) { - it->func((ble_evt_t *)m_ble_evt_buf, it->param); + done = it->func(event, it->param) || done; it = it->next; } + if (!done) { + //mp_printf(&mp_plat_print, "Unhandled ble event: 0x%04x\n", event->header.evt_id); + } } } diff --git a/ports/nrf/bluetooth/ble_drv.h b/ports/nrf/bluetooth/ble_drv.h index a066f588fa..7716cab8be 100644 --- a/ports/nrf/bluetooth/ble_drv.h +++ b/ports/nrf/bluetooth/ble_drv.h @@ -29,6 +29,8 @@ #ifndef MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_DRV_H #define MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_DRV_H +#include + #include "ble.h" #define MAX_TX_IN_PROGRESS 10 @@ -48,7 +50,7 @@ #define UNIT_1_25_MS (1250) #define UNIT_10_MS (10000) -typedef void (*ble_drv_evt_handler_t)(ble_evt_t*, void*); +typedef bool (*ble_drv_evt_handler_t)(ble_evt_t*, void*); typedef enum { SD_FLASH_OPERATION_DONE, @@ -69,4 +71,7 @@ void ble_drv_reset(void); void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param); void ble_drv_remove_event_handler(ble_drv_evt_handler_t func, void *param); +// Allow for user provided entries to prevent allocations outside the VM. +void ble_drv_add_event_handler_entry(ble_drv_evt_handler_entry_t* entry, ble_drv_evt_handler_t func, void *param); + #endif // MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_DRV_H diff --git a/ports/nrf/boards/adafruit_nrf52840_s140_v6.ld b/ports/nrf/boards/adafruit_nrf52840_s140_v6.ld index 2587a19e34..756060f960 100644 --- a/ports/nrf/boards/adafruit_nrf52840_s140_v6.ld +++ b/ports/nrf/boards/adafruit_nrf52840_s140_v6.ld @@ -16,6 +16,7 @@ 0x00000000..0x00000FFF (4KB) Master Boot Record */ + /* Specify the memory areas (S140 6.x.x) */ MEMORY { @@ -26,7 +27,10 @@ MEMORY FLASH_FATFS (r) : ORIGIN = 0x000AD000, LENGTH = 0x040000 /* 0x2000000 - RAM:ORIGIN is reserved for Softdevice */ - RAM (xrw) : ORIGIN = 0x20004000, LENGTH = 0x20040000 - 0x20004000 + /* SoftDevice 6.1.0 takes 0x1628 bytes (5.54 kb) minimum. */ + /* To measure the minimum required amount of memory for given configuration, set this number + high enough to work and then check the mutation of the value done by sd_ble_enable. */ + RAM (xrw) : ORIGIN = 0x20000000 + 16K, LENGTH = 256K - 16K } /* produce a link error if there is not this amount of RAM for these sections */ @@ -38,7 +42,8 @@ _minimum_heap_size = 0; /*_stack_end = ORIGIN(RAM) + LENGTH(RAM);*/ _estack = ORIGIN(RAM) + LENGTH(RAM); -/* RAM extents for the garbage collector */ +/* RAM extents for the garbage collector and soft device init */ +_ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_end = 0x20020000; /* tunable */ diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index a8e1f19059..295a42d63b 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -26,6 +26,7 @@ * THE SOFTWARE. */ +#include #include #include @@ -34,11 +35,18 @@ #include "nrfx_power.h" #include "nrf_nvic.h" #include "nrf_sdm.h" +#include "tick.h" +#include "py/gc.h" #include "py/objstr.h" #include "py/runtime.h" +#include "supervisor/shared/safe_mode.h" #include "supervisor/usb.h" +#include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" #include "shared-bindings/_bleio/Address.h" +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/ScanEntry.h" +#include "shared-bindings/time/__init__.h" #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) #define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) @@ -46,10 +54,13 @@ #define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { - mp_raise_msg_varg(&mp_type_AssertionError, - translate("Soft device assert, id: 0x%08lX, pc: 0x%08lX"), id, pc); + reset_into_safe_mode(NORDIC_SOFT_DEVICE_ASSERT); } +bleio_connection_internal_t connections[BLEIO_TOTAL_CONNECTION_COUNT]; + +// Linker script provided ram start. +extern uint32_t _ram_start; STATIC uint32_t ble_stack_enable(void) { nrf_clock_lf_cfg_t clock_config = { #if BOARD_HAS_32KHZ_XTAL @@ -78,34 +89,56 @@ STATIC uint32_t ble_stack_enable(void) { // Start with no event handlers, etc. ble_drv_reset(); - uint32_t app_ram_start; - app_ram_start = 0x20004000; + // Set everything up to have one persistent code editing connection and one user managed + // connection. In the future we could move .data and .bss to the other side of the stack and + // dynamically adjust for different memory requirements of the SD based on boot.py + // configuration. + uint32_t app_ram_start = (uint32_t) &_ram_start; ble_cfg_t ble_conf; ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM; - ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = BLE_GAP_CONN_COUNT_DEFAULT; + ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = BLEIO_TOTAL_CONNECTION_COUNT; + // Event length here can influence throughput so perhaps make multiple connection profiles + // available. ble_conf.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT; err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_conf, app_ram_start); - if (err_code != NRF_SUCCESS) + if (err_code != NRF_SUCCESS) { return err_code; + } memset(&ble_conf, 0, sizeof(ble_conf)); - ble_conf.gap_cfg.role_count_cfg.periph_role_count = 1; + ble_conf.gap_cfg.role_count_cfg.adv_set_count = 1; + ble_conf.gap_cfg.role_count_cfg.periph_role_count = 2; ble_conf.gap_cfg.role_count_cfg.central_role_count = 1; err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_conf, app_ram_start); - if (err_code != NRF_SUCCESS) + if (err_code != NRF_SUCCESS) { return err_code; + } memset(&ble_conf, 0, sizeof(ble_conf)); ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM; ble_conf.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = MAX_TX_IN_PROGRESS; err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_conf, app_ram_start); - if (err_code != NRF_SUCCESS) + if (err_code != NRF_SUCCESS) { return err_code; + } - err_code = sd_ble_enable(&app_ram_start); - if (err_code != NRF_SUCCESS) + // Triple the GATT Server attribute size to accomodate both the CircuitPython built-in service + // and anything the user does. + memset(&ble_conf, 0, sizeof(ble_conf)); + ble_conf.gatts_cfg.attr_tab_size.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT * 3; + err_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_conf, app_ram_start); + if (err_code != NRF_SUCCESS) { return err_code; + } + + // TODO set ATT_MTU so that the maximum MTU we can negotiate is higher than the default. + + // This sets app_ram_start to the minimum value needed for the settings set above. + err_code = sd_ble_enable(&app_ram_start); + if (err_code != NRF_SUCCESS) { + return err_code; + } ble_gap_conn_params_t gap_conn_params = { .min_conn_interval = BLE_MIN_CONN_INTERVAL, @@ -122,11 +155,109 @@ STATIC uint32_t ble_stack_enable(void) { return err_code; } -void common_hal_bleio_adapter_set_enabled(bool enabled) { - const bool is_enabled = common_hal_bleio_adapter_get_enabled(); +STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { + bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in; + + // For debugging. + // mp_printf(&mp_plat_print, "Adapter event: 0x%04x\n", ble_evt->header.evt_id); + + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: { + // Find an empty connection. One must always be available because the SD has the same + // total connection limit. + bleio_connection_internal_t *connection; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + connection = &connections[i]; + if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) { + break; + } + } + + // Central has connected. + ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected; + + connection->conn_handle = ble_evt->evt.gap_evt.conn_handle; + connection->connection_obj = mp_const_none; + ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection); + self->connection_objs = NULL; + + // See if connection interval set by Central is out of range. + // If so, negotiate our preferred range. + ble_gap_conn_params_t conn_params; + sd_ble_gap_ppcp_get(&conn_params); + if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval || + conn_params.min_conn_interval > connected->conn_params.max_conn_interval) { + sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); + } + self->current_advertising_data = NULL; + break; + } + case BLE_GAP_EVT_DISCONNECTED: { + // Find the connection that was disconnected. + bleio_connection_internal_t *connection; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + connection = &connections[i]; + if (connection->conn_handle == ble_evt->evt.gap_evt.conn_handle) { + break; + } + } + ble_drv_remove_event_handler(connection_on_ble_evt, connection); + connection->conn_handle = BLE_CONN_HANDLE_INVALID; + if (connection->connection_obj != mp_const_none) { + bleio_connection_obj_t* obj = connection->connection_obj; + obj->connection = NULL; + obj->disconnect_reason = ble_evt->evt.gap_evt.params.disconnected.reason; + } + self->connection_objs = NULL; + + break; + } + + case BLE_GAP_EVT_ADV_SET_TERMINATED: + self->current_advertising_data = NULL; + break; + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled adapter event: 0x%04x\n", ble_evt->header.evt_id); + return false; + break; + } + return true; +} + +STATIC void get_address(bleio_adapter_obj_t *self, ble_gap_addr_t *address) { + uint32_t err_code; + + err_code = sd_ble_gap_addr_get(address); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg(translate("Failed to get local address")); + } +} + +char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 , 0}; + +STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { + uint8_t len = sizeof(default_ble_name) - 1; + + ble_gap_addr_t local_address; + get_address(self, &local_address); + + default_ble_name[len - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf]; + default_ble_name[len - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf]; + default_ble_name[len - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf]; + default_ble_name[len - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf]; + default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings + + common_hal_bleio_adapter_set_name(self, (char*) default_ble_name); +} + +void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) { + const bool is_enabled = common_hal_bleio_adapter_get_enabled(self); // Don't enable or disable twice - if ((is_enabled && enabled) || (!is_enabled && !enabled)) { + if (is_enabled == enabled) { return; } @@ -137,22 +268,34 @@ void common_hal_bleio_adapter_set_enabled(bool enabled) { nrfx_power_uninit(); err_code = ble_stack_enable(); - - // Re-init USB hardware - init_usb_hardware(); } else { err_code = sd_softdevice_disable(); - - // Re-init USB hardware - init_usb_hardware(); } + // Re-init USB hardware + init_usb_hardware(); if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg(translate("Failed to change softdevice state")); + mp_raise_OSError_msg_varg(translate("Failed to change softdevice state, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } + + // Add a handler for incoming peripheral connections. + if (enabled) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + connection->conn_handle = BLE_CONN_HANDLE_INVALID; + } + bleio_adapter_reset_name(self); + ble_drv_add_event_handler_entry(&self->handler_entry, adapter_on_ble_evt, self); + } else { + ble_drv_reset(); + self->scan_results = NULL; + self->current_advertising_data = NULL; + self->advertising_data = NULL; + self->scan_response_data = NULL; } } -bool common_hal_bleio_adapter_get_enabled(void) { +bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) { uint8_t is_enabled; const uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); @@ -163,22 +306,11 @@ bool common_hal_bleio_adapter_get_enabled(void) { return is_enabled; } -void get_address(ble_gap_addr_t *address) { - uint32_t err_code; - - common_hal_bleio_adapter_set_enabled(true); - err_code = sd_ble_gap_addr_get(address); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg(translate("Failed to get local address")); - } -} - -bleio_address_obj_t *common_hal_bleio_adapter_get_address(void) { - common_hal_bleio_adapter_set_enabled(true); +bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) { + common_hal_bleio_adapter_set_enabled(self, true); ble_gap_addr_t local_address; - get_address(&local_address); + get_address(self, &local_address); bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); address->base.type = &bleio_address_type; @@ -187,18 +319,326 @@ bleio_address_obj_t *common_hal_bleio_adapter_get_address(void) { return address; } -mp_obj_t common_hal_bleio_adapter_get_default_name(void) { - common_hal_bleio_adapter_set_enabled(true); - - ble_gap_addr_t local_address; - get_address(&local_address); - - char name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 }; - - name[sizeof(name) - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf]; - name[sizeof(name) - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf]; - name[sizeof(name) - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf]; - name[sizeof(name) - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf]; - - return mp_obj_new_str(name, sizeof(name)); +mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) { + uint16_t len = 0; + sd_ble_gap_device_name_get(NULL, &len); + uint8_t buf[len]; + uint32_t err_code = sd_ble_gap_device_name_get(buf, &len); + if (err_code != NRF_SUCCESS) { + return NULL; + } + return mp_obj_new_str((char*) buf, len); +} + +void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name) { + ble_gap_conn_sec_mode_t sec; + sec.lv = 0; + sec.sm = 0; + sd_ble_gap_device_name_set(&sec, (const uint8_t*) name, strlen(name)); +} + +STATIC bool scan_on_ble_evt(ble_evt_t *ble_evt, void *scan_results_in) { + bleio_scanresults_obj_t *scan_results = (bleio_scanresults_obj_t*)scan_results_in; + + if (ble_evt->header.evt_id == BLE_GAP_EVT_TIMEOUT && + ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN) { + shared_module_bleio_scanresults_set_done(scan_results, true); + ble_drv_remove_event_handler(scan_on_ble_evt, scan_results); + return true; + } + + if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) { + return false; + } + ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; + + shared_module_bleio_scanresults_append(scan_results, + ticks_ms, + report->type.connectable, + report->type.scan_response, + report->rssi, + report->peer_addr.addr, + report->peer_addr.addr_type, + report->data.p_data, + report->data.len); + + const uint32_t err_code = sd_ble_gap_scan_start(NULL, scan_results->common_hal_data); + if (err_code != NRF_SUCCESS) { + // TODO: Pass the error into the scan results so it can throw an exception. + scan_results->done = true; + } + return true; +} + +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) { + if (self->scan_results != NULL) { + if (!shared_module_bleio_scanresults_get_done(self->scan_results)) { + mp_raise_RuntimeError(translate("Scan already in progess. Stop with stop_scan.")); + } + self->scan_results = NULL; + } + self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi); + size_t max_packet_size = extended ? BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED : BLE_GAP_SCAN_BUFFER_MAX; + uint8_t *raw_data = m_malloc(sizeof(ble_data_t) + max_packet_size, false); + ble_data_t * sd_data = (ble_data_t *) raw_data; + self->scan_results->common_hal_data = sd_data; + sd_data->len = max_packet_size; + sd_data->p_data = raw_data + sizeof(ble_data_t); + + ble_drv_add_event_handler(scan_on_ble_evt, self->scan_results); + + uint32_t nrf_timeout = SEC_TO_UNITS(timeout, UNIT_10_MS); + if (timeout <= 0.0001) { + nrf_timeout = BLE_GAP_SCAN_TIMEOUT_UNLIMITED; + } + + ble_gap_scan_params_t scan_params = { + .extended = extended, + .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), + .timeout = nrf_timeout, + .window = SEC_TO_UNITS(window, UNIT_0_625_MS), + .scan_phys = BLE_GAP_PHY_1MBPS, + .active = active + }; + uint32_t err_code; + err_code = sd_ble_gap_scan_start(&scan_params, sd_data); + + if (err_code != NRF_SUCCESS) { + self->scan_results = NULL; + ble_drv_remove_event_handler(scan_on_ble_evt, self->scan_results); + mp_raise_OSError_msg_varg(translate("Failed to start scanning, err 0x%04x"), err_code); + } + + return MP_OBJ_FROM_PTR(self->scan_results); +} + +void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) { + sd_ble_gap_scan_stop(); + shared_module_bleio_scanresults_set_done(self->scan_results, true); + ble_drv_remove_event_handler(scan_on_ble_evt, self->scan_results); + self->scan_results = NULL; +} + +typedef struct { + uint16_t conn_handle; + volatile bool done; +} connect_info_t; + +STATIC bool connect_on_ble_evt(ble_evt_t *ble_evt, void *info_in) { + connect_info_t *info = (connect_info_t*)info_in; + + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + info->conn_handle = ble_evt->evt.gap_evt.conn_handle; + info->done = true; + + break; + + case BLE_GAP_EVT_TIMEOUT: + // Handle will be invalid. + info->done = true; + break; + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id); + return false; + break; + } + return true; +} + +mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, bool pair) { + + ble_gap_addr_t addr; + + addr.addr_type = address->type; + mp_buffer_info_t address_buf_info; + mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ); + memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES); + + ble_gap_scan_params_t scan_params = { + .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), + .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), + .scan_phys = BLE_GAP_PHY_1MBPS, + // timeout of 0 means no timeout + .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS), + }; + + ble_gap_conn_params_t conn_params = { + .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS), + .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS), + .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS), + .slave_latency = 0, // number of conn events + }; + + connect_info_t event_info; + ble_drv_add_event_handler(connect_on_ble_evt, &event_info); + event_info.done = false; + + uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); + + if (err_code != NRF_SUCCESS) { + ble_drv_remove_event_handler(connect_on_ble_evt, &event_info); + mp_raise_OSError_msg_varg(translate("Failed to start connecting, error 0x%04x"), err_code); + } + + while (!event_info.done) { + RUN_BACKGROUND_TASKS; + } + + ble_drv_remove_event_handler(connect_on_ble_evt, &event_info); + + if (event_info.conn_handle == BLE_CONN_HANDLE_INVALID) { + mp_raise_OSError_msg(translate("Failed to connect: timeout")); + } + + // Make the connection object and return it. + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + if (connection->conn_handle == event_info.conn_handle) { + return bleio_connection_new_from_internal(connection); + } + } + + mp_raise_OSError_msg(translate("Failed to connect: internal error")); + + return mp_const_none; +} + +// The nRF SD 6.1.0 can only do one concurrent advertisement so share the advertising handle. +uint8_t adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; + +STATIC void check_data_fit(size_t data_len) { + if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) { + mp_raise_ValueError(translate("Data too large for advertisement packet")); + } +} + +uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len) { + if (self->current_advertising_data != NULL && self->current_advertising_data == self->advertising_data) { + return NRF_ERROR_BUSY; + } + + // If the current advertising data isn't owned by the adapter then it must be an internal + // advertisement that we should stop. + if (self->current_advertising_data != NULL) { + common_hal_bleio_adapter_stop_advertising(self); + } + + uint32_t err_code; + ble_gap_adv_params_t adv_params = { + .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), + .properties.type = connectable ? BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED + : BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED, + .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED, + .filter_policy = BLE_GAP_ADV_FP_ANY, + .primary_phy = BLE_GAP_PHY_1MBPS, + }; + + const ble_gap_adv_data_t ble_gap_adv_data = { + .adv_data.p_data = advertising_data, + .adv_data.len = advertising_data_len, + .scan_rsp_data.p_data = scan_response_data_len > 0 ? scan_response_data : NULL, + .scan_rsp_data.len = scan_response_data_len, + }; + + err_code = sd_ble_gap_adv_set_configure(&adv_handle, &ble_gap_adv_data, &adv_params); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + err_code = sd_ble_gap_adv_start(adv_handle, BLE_CONN_CFG_TAG_CUSTOM); + if (err_code != NRF_SUCCESS) { + return err_code; + } + self->current_advertising_data = advertising_data; + return NRF_SUCCESS; +} + + +void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) { + if (self->current_advertising_data != NULL && self->current_advertising_data == self->advertising_data) { + mp_raise_OSError_msg(translate("Already advertising.")); + } + // interval value has already been validated. + + uint32_t err_code; + + check_data_fit(advertising_data_bufinfo->len); + check_data_fit(scan_response_data_bufinfo->len); + // The advertising data buffers must not move, because the SoftDevice depends on them. + // So make them long-lived and reuse them onwards. + if (self->advertising_data == NULL) { + self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true); + } + if (self->scan_response_data == NULL) { + self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true); + } + + memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len); + memcpy(self->scan_response_data, scan_response_data_bufinfo->buf, scan_response_data_bufinfo->len); + + err_code = _common_hal_bleio_adapter_start_advertising(self, connectable, interval, self->advertising_data, advertising_data_bufinfo->len, self->scan_response_data, scan_response_data_bufinfo->len); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to start advertising, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } +} + +void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { + if (adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) + return; + + // TODO: Don't actually stop. Switch to advertising CircuitPython if we don't already have a connection. + const uint32_t err_code = sd_ble_gap_adv_stop(adv_handle); + self->current_advertising_data = NULL; + + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) { + mp_raise_OSError_msg_varg(translate("Failed to stop advertising, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } +} + +bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) { + return true; + } + } + return false; +} + +mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { + if (self->connection_objs != NULL) { + return self->connection_objs; + } + size_t total_connected = 0; + mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT]; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) { + if (connection->connection_obj == mp_const_none) { + connection->connection_obj = bleio_connection_new_from_internal(connection); + } + items[total_connected] = connection->connection_obj; + total_connected++; + } + } + self->connection_objs = mp_obj_new_tuple(total_connected, items); + return self->connection_objs; +} + +void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) { + gc_collect_root((void**)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t)); + gc_collect_root((void**)connections, sizeof(connections) / sizeof(size_t)); +} + +void bleio_adapter_reset(bleio_adapter_obj_t* adapter) { + common_hal_bleio_adapter_stop_scan(adapter); + common_hal_bleio_adapter_stop_advertising(adapter); + adapter->connection_objs = NULL; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + connection->connection_obj = mp_const_none; + } } diff --git a/ports/nrf/common-hal/_bleio/Adapter.h b/ports/nrf/common-hal/_bleio/Adapter.h index 5dcc625406..dca4439908 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.h +++ b/ports/nrf/common-hal/_bleio/Adapter.h @@ -30,9 +30,27 @@ #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ADAPTER_H #include "py/obj.h" +#include "py/objtuple.h" + +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/ScanResults.h" + +#define BLEIO_TOTAL_CONNECTION_COUNT 2 + +extern bleio_connection_internal_t connections[BLEIO_TOTAL_CONNECTION_COUNT]; typedef struct { mp_obj_base_t base; -} super_adapter_obj_t; + uint8_t* advertising_data; + uint8_t* scan_response_data; + uint8_t* current_advertising_data; + bleio_scanresults_obj_t* scan_results; + mp_obj_t name; + mp_obj_tuple_t *connection_objs; + ble_drv_evt_handler_entry_t handler_entry; +} bleio_adapter_obj_t; + +void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter); +void bleio_adapter_reset(bleio_adapter_obj_t* adapter); #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ADAPTER_H diff --git a/ports/nrf/common-hal/_bleio/Central.c b/ports/nrf/common-hal/_bleio/Central.c deleted file mode 100644 index db67b763c6..0000000000 --- a/ports/nrf/common-hal/_bleio/Central.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * 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 -#include - -#include "ble.h" -#include "ble_drv.h" -#include "ble_hci.h" -#include "nrf_soc.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "shared-bindings/_bleio/__init__.h" -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Central.h" - -STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { - bleio_central_obj_t *central = (bleio_central_obj_t*)central_in; - - switch (ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - central->conn_handle = ble_evt->evt.gap_evt.conn_handle; - central->waiting_to_connect = false; - break; - - case BLE_GAP_EVT_TIMEOUT: - // Handle will be invalid. - central->waiting_to_connect = false; - break; - - case BLE_GAP_EVT_DISCONNECTED: - central->conn_handle = BLE_CONN_HANDLE_INVALID; - break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - sd_ble_gap_sec_params_reply(central->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); - break; - - case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { - ble_gap_evt_conn_param_update_request_t *request = - &ble_evt->evt.gap_evt.params.conn_param_update_request; - sd_ble_gap_conn_param_update(central->conn_handle, &request->conn_params); - break; - } - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} - -void common_hal_bleio_central_construct(bleio_central_obj_t *self) { - common_hal_bleio_adapter_set_enabled(true); - - self->remote_service_list = mp_obj_new_list(0, NULL); - self->conn_handle = BLE_CONN_HANDLE_INVALID; -} - -void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) { - common_hal_bleio_adapter_set_enabled(true); - ble_drv_add_event_handler(central_on_ble_evt, self); - - ble_gap_addr_t addr; - - addr.addr_type = address->type; - mp_buffer_info_t address_buf_info; - mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ); - memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES); - - ble_gap_scan_params_t scan_params = { - .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), - .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), - .scan_phys = BLE_GAP_PHY_1MBPS, - // timeout of 0 means no timeout - .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS), - }; - - ble_gap_conn_params_t conn_params = { - .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS), - .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS), - .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS), - .slave_latency = 0, // number of conn events - }; - - self->waiting_to_connect = true; - - uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to start connecting, error 0x%04x"), err_code); - } - - while (self->waiting_to_connect) { - RUN_BACKGROUND_TASKS; - } - - if (self->conn_handle == BLE_CONN_HANDLE_INVALID) { - mp_raise_OSError_msg(translate("Failed to connect: timeout")); - } -} - -void common_hal_bleio_central_disconnect(bleio_central_obj_t *self) { - sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); -} - -bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self) { - return self->conn_handle != BLE_CONN_HANDLE_INVALID; -} - -mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist) { - common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist); - // Convert to a tuple and then clear the list so the callee will take ownership. - mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_service_list->len, - self->remote_service_list->items); - mp_obj_list_clear(self->remote_service_list); - return services_tuple; -} - -mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) { - return self->remote_service_list; -} diff --git a/ports/nrf/common-hal/_bleio/Characteristic.c b/ports/nrf/common-hal/_bleio/Characteristic.c index e8454d528c..ab765d1ed3 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.c +++ b/ports/nrf/common-hal/_bleio/Characteristic.c @@ -32,7 +32,7 @@ #include "shared-bindings/_bleio/Descriptor.h" #include "shared-bindings/_bleio/Service.h" -static volatile bleio_characteristic_obj_t *m_read_characteristic; +#include "common-hal/_bleio/Adapter.h" STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) { uint16_t cccd; @@ -53,27 +53,6 @@ STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_hand return cccd; } -STATIC void characteristic_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { - switch (ble_evt->header.evt_id) { - - // More events may be handled later, so keep this as a switch. - - case BLE_GATTC_EVT_READ_RSP: { - ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; - if (m_read_characteristic) { - m_read_characteristic->value = mp_obj_new_bytearray(response->len, response->data); - } - // Indicate to busy-wait loop that we've read the attribute value. - m_read_characteristic = NULL; - break; - } - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, uint16_t hvx_type) { uint16_t hvx_len = bufinfo->len; @@ -103,35 +82,14 @@ STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_ } } -STATIC void characteristic_gattc_read(bleio_characteristic_obj_t *characteristic) { - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); - common_hal_bleio_check_connected(conn_handle); - - // Set to NULL in event loop after event. - m_read_characteristic = characteristic; - - ble_drv_add_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic); - - const uint32_t err_code = sd_ble_gattc_read(conn_handle, characteristic->handle, 0); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code); - } - - while (m_read_characteristic != NULL) { - RUN_BACKGROUND_TASKS; - } - - ble_drv_remove_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic); -} - -void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { self->service = service; self->uuid = uuid; self->handle = BLE_GATT_HANDLE_INVALID; self->props = props; self->read_perm = read_perm; self->write_perm = write_perm; - self->descriptor_list = mp_obj_new_list(0, NULL); + self->descriptor_list = NULL; const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX; if (max_length < 0 || max_length > max_length_max) { @@ -141,10 +99,18 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->max_length = max_length; self->fixed_length = fixed_length; - common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo); + if (service->is_remote) { + self->handle = handle; + } else { + common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo); + } + + if (initial_value_bufinfo != NULL) { + common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo); + } } -mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) { +bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) { return self->descriptor_list; } @@ -152,19 +118,19 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character return self->service; } -mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) { +size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len) { // Do GATT operations only if this characteristic has been added to a registered service. if (self->handle != BLE_GATT_HANDLE_INVALID) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); if (common_hal_bleio_service_get_is_remote(self->service)) { // self->value is set by evt handler. - characteristic_gattc_read(self); + return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); } else { - self->value = common_hal_bleio_gatts_read(self->handle, conn_handle); + return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); } } - return self->value; + return 0; } void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { @@ -175,39 +141,40 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_raise_ValueError(translate("Value length > max_length")); } - self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len); - // Do GATT operations only if this characteristic has been added to a registered service. if (self->handle != BLE_GATT_HANDLE_INVALID) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); if (common_hal_bleio_service_get_is_remote(self->service)) { + uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); // Last argument is true if write-no-reponse desired. common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, (self->props & CHAR_PROP_WRITE_NO_RESPONSE)); } else { + // Always write the value locally even if no connections are active. + common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo); + // Check to see if we need to notify or indicate any active connections. + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &connections[i]; + uint16_t conn_handle = connection->conn_handle; + if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) { + continue; + } - bool sent = false; - uint16_t cccd = 0; + uint16_t cccd = 0; - const bool notify = self->props & CHAR_PROP_NOTIFY; - const bool indicate = self->props & CHAR_PROP_INDICATE; - if (notify | indicate) { - cccd = characteristic_get_cccd(self->cccd_handle, conn_handle); - } + const bool notify = self->props & CHAR_PROP_NOTIFY; + const bool indicate = self->props & CHAR_PROP_INDICATE; + if (notify | indicate) { + cccd = characteristic_get_cccd(self->cccd_handle, conn_handle); + } - // It's possible that both notify and indicate are set. - if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { - characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION); - sent = true; - } - if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { - characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION); - sent = true; - } - - if (!sent) { - common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + // It's possible that both notify and indicate are set. + if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { + characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION); + } + if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { + characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION); + } } } } @@ -252,7 +219,8 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t * mp_raise_OSError_msg_varg(translate("Failed to add descriptor, err 0x%04x"), err_code); } - mp_obj_list_append(self->descriptor_list, MP_OBJ_FROM_PTR(descriptor)); + descriptor->next = self->descriptor_list; + self->descriptor_list = descriptor; } void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { @@ -264,7 +232,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, mp_raise_ValueError(translate("Can't set CCCD on local Characteristic")); } - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); common_hal_bleio_check_connected(conn_handle); uint16_t cccd_value = diff --git a/ports/nrf/common-hal/_bleio/Characteristic.h b/ports/nrf/common-hal/_bleio/Characteristic.h index 3a7691d07f..bb8f28495e 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.h +++ b/ports/nrf/common-hal/_bleio/Characteristic.h @@ -29,11 +29,12 @@ #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H #include "shared-bindings/_bleio/Attribute.h" +#include "common-hal/_bleio/Descriptor.h" #include "shared-module/_bleio/Characteristic.h" #include "common-hal/_bleio/Service.h" #include "common-hal/_bleio/UUID.h" -typedef struct { +typedef struct _bleio_characteristic_obj { mp_obj_base_t base; // Will be MP_OBJ_NULL before being assigned to a Service. bleio_service_obj_t *service; @@ -45,7 +46,7 @@ typedef struct { bleio_characteristic_properties_t props; bleio_attribute_security_mode_t read_perm; bleio_attribute_security_mode_t write_perm; - mp_obj_list_t *descriptor_list; + bleio_descriptor_obj_t *descriptor_list; uint16_t user_desc_handle; uint16_t cccd_handle; uint16_t sccd_handle; diff --git a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c index 95794feec0..5f280e121f 100644 --- a/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/nrf/common-hal/_bleio/CharacteristicBuffer.c @@ -38,6 +38,7 @@ #include "tick.h" #include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Connection.h" #include "common-hal/_bleio/CharacteristicBuffer.h" STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) { @@ -50,7 +51,7 @@ STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *d sd_nvic_critical_region_exit(is_nested_critical_region); } -STATIC void characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { +STATIC bool characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param; switch (ble_evt->header.evt_id) { case BLE_GATTS_EVT_WRITE: { @@ -75,7 +76,11 @@ STATIC void characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { } break; } + default: + return false; + break; } + return true; } // Assumes that timeout and buffer_size have been validated before call. @@ -150,6 +155,7 @@ void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_o bool common_hal_bleio_characteristic_buffer_connected(bleio_characteristic_buffer_obj_t *self) { return self->characteristic != NULL && self->characteristic->service != NULL && - self->characteristic->service->device != NULL && - common_hal_bleio_device_get_conn_handle(self->characteristic->service->device) != BLE_CONN_HANDLE_INVALID; + (!self->characteristic->service->is_remote || + (self->characteristic->service->connection != MP_OBJ_NULL && + common_hal_bleio_connection_get_connected(self->characteristic->service->connection))); } diff --git a/ports/nrf/common-hal/_bleio/Connection.c b/ports/nrf/common-hal/_bleio/Connection.c new file mode 100644 index 0000000000..5d3e3ace11 --- /dev/null +++ b/ports/nrf/common-hal/_bleio/Connection.c @@ -0,0 +1,629 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * 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/Connection.h" + +#include +#include + +#include "ble.h" +#include "ble_drv.h" +#include "ble_hci.h" +#include "nrf_soc.h" +#include "py/gc.h" +#include "py/objlist.h" +#include "py/objstr.h" +#include "py/qstr.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Attribute.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" + +#define BLE_ADV_LENGTH_FIELD_SIZE 1 +#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 +#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 + +static const ble_gap_sec_params_t pairing_sec_params = { + .bond = 1, + .mitm = 0, + .lesc = 0, + .keypress = 0, + .oob = 0, + .io_caps = BLE_GAP_IO_CAPS_NONE, + .min_key_size = 7, + .max_key_size = 16, + .kdist_own = { .enc = 1, .id = 1}, + .kdist_peer = { .enc = 1, .id = 1}, +}; + +static volatile bool m_discovery_in_process; +static volatile bool m_discovery_successful; + +static bleio_service_obj_t *m_char_discovery_service; +static bleio_characteristic_obj_t *m_desc_discovery_characteristic; + +bool dump_events = false; + +bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { + bleio_connection_internal_t *self = (bleio_connection_internal_t*)self_in; + + if (BLE_GAP_EVT_BASE <= ble_evt->header.evt_id && ble_evt->header.evt_id <= BLE_GAP_EVT_LAST && + ble_evt->evt.gap_evt.conn_handle != self->conn_handle) { + return false; + } + if (BLE_GATTS_EVT_BASE <= ble_evt->header.evt_id && ble_evt->header.evt_id <= BLE_GATTS_EVT_LAST && + ble_evt->evt.gatts_evt.conn_handle != self->conn_handle) { + return false; + } + + // For debugging. + if (dump_events) { + mp_printf(&mp_plat_print, "Connection event: 0x%04x\n", ble_evt->header.evt_id); + } + + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_DISCONNECTED: + break; + case BLE_GAP_EVT_CONN_PARAM_UPDATE: // 0x12 + break; + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { + ble_gap_phys_t const phys = { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys); + break; + } + + case BLE_GAP_EVT_PHY_UPDATE: // 0x22 + break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: + // SoftDevice will respond to a length update request. + sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL); + break; + + case BLE_GAP_EVT_DATA_LENGTH_UPDATE: // 0x24 + break; + + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: { + // We only handle MTU of size BLE_GATT_ATT_MTU_DEFAULT. + sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATT_ATT_MTU_DEFAULT); + break; + } + + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); + break; + + case BLE_GATTS_EVT_HVN_TX_COMPLETE: // Capture this for now. 0x55 + break; + + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { + ble_gap_evt_conn_param_update_request_t *request = + &ble_evt->evt.gap_evt.params.conn_param_update_request; + sd_ble_gap_conn_param_update(self->conn_handle, &request->conn_params); + break; + } + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { + ble_gap_sec_keyset_t keyset = { + .keys_own = { + .p_enc_key = &self->bonding_keys.own_enc, + .p_id_key = NULL, + .p_sign_key = NULL, + .p_pk = NULL + }, + + .keys_peer = { + .p_enc_key = &self->bonding_keys.peer_enc, + .p_id_key = &self->bonding_keys.peer_id, + .p_sign_key = NULL, + .p_pk = NULL + } + }; + + sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, + &pairing_sec_params, &keyset); + break; + } + + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: + // TODO for LESC pairing: + // sd_ble_gap_lesc_dhkey_reply(...); + break; + + case BLE_GAP_EVT_AUTH_STATUS: { // 0x19 + // Pairing process completed + ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status; + if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status) { + // TODO _ediv = bonding_keys->own_enc.master_id.ediv; + self->pair_status = PAIR_PAIRED; + } else { + self->pair_status = PAIR_NOT_PAIRED; + } + break; + } + + case BLE_GAP_EVT_SEC_INFO_REQUEST: { // 0x14 + // Peer asks for the stored keys. + // - load key and return if bonded previously. + // - Else return NULL --> Initiate key exchange + ble_gap_evt_sec_info_request_t* sec_info_request = &ble_evt->evt.gap_evt.params.sec_info_request; + (void) sec_info_request; + //if ( bond_load_keys(_role, sec_req->master_id.ediv, &bkeys) ) { + //sd_ble_gap_sec_info_reply(_conn_hdl, &bkeys.own_enc.enc_info, &bkeys.peer_id.id_info, NULL); + // + //_ediv = bkeys.own_enc.master_id.ediv; + // } else { + sd_ble_gap_sec_info_reply(self->conn_handle, NULL, NULL, NULL); + // } + break; + } + + case BLE_GAP_EVT_CONN_SEC_UPDATE: { // 0x1a + ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec; + if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) { + // Security setup did not succeed: + // mode 0, level 0 means no access + // mode 1, level 1 means open link + // mode >=1 and/or level >=1 means encryption is set up + self->pair_status = PAIR_NOT_PAIRED; + } else { + //if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) { + if (true) { // TODO: no bonding yet + // Initialize system attributes fresh. + sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); + } + // Not quite paired yet: wait for BLE_GAP_EVT_AUTH_STATUS SUCCESS. + self->ediv = self->bonding_keys.own_enc.master_id.ediv; + } + break; + } + + + default: + // For debugging. + if (dump_events) { + mp_printf(&mp_plat_print, "Unhandled connection event: 0x%04x\n", ble_evt->header.evt_id); + } + + return false; + } + return true; +} + +void bleio_connection_clear(bleio_connection_internal_t *self) { + self->remote_service_list = NULL; + + self->conn_handle = BLE_CONN_HANDLE_INVALID; + self->pair_status = PAIR_NOT_PAIRED; + + memset(&self->bonding_keys, 0, sizeof(self->bonding_keys)); +} + +bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) { + if (self->connection == NULL) { + return false; + } + return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID; +} + +void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) { + sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); +} + +void common_hal_bleio_connection_pair(bleio_connection_internal_t *self) { + self->pair_status = PAIR_WAITING; + + uint32_t err_code = sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to start pairing, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } + + while (self->pair_status == PAIR_WAITING) { + RUN_BACKGROUND_TASKS; + } + + if (self->pair_status == PAIR_NOT_PAIRED) { + mp_raise_OSError_msg(translate("Failed to pair")); + } +} + + +// service_uuid may be NULL, to discover all services. +STATIC bool discover_next_services(bleio_connection_internal_t* connection, uint16_t start_handle, ble_uuid_t *service_uuid) { + m_discovery_successful = false; + m_discovery_in_process = true; + + uint32_t err_code = sd_ble_gattc_primary_services_discover(connection->conn_handle, start_handle, service_uuid); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg(translate("Failed to discover services")); + } + + // Wait for a discovery event. + while (m_discovery_in_process) { + MICROPY_VM_HOOK_LOOP; + } + return m_discovery_successful; +} + +STATIC bool discover_next_characteristics(bleio_connection_internal_t* connection, bleio_service_obj_t *service, uint16_t start_handle) { + m_char_discovery_service = service; + + ble_gattc_handle_range_t handle_range; + handle_range.start_handle = start_handle; + handle_range.end_handle = service->end_handle; + + m_discovery_successful = false; + m_discovery_in_process = true; + + uint32_t err_code = sd_ble_gattc_characteristics_discover(connection->conn_handle, &handle_range); + if (err_code != NRF_SUCCESS) { + return false; + } + + // Wait for a discovery event. + while (m_discovery_in_process) { + MICROPY_VM_HOOK_LOOP; + } + return m_discovery_successful; +} + +STATIC bool discover_next_descriptors(bleio_connection_internal_t* connection, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) { + m_desc_discovery_characteristic = characteristic; + + ble_gattc_handle_range_t handle_range; + handle_range.start_handle = start_handle; + handle_range.end_handle = end_handle; + + m_discovery_successful = false; + m_discovery_in_process = true; + + uint32_t err_code = sd_ble_gattc_descriptors_discover(connection->conn_handle, &handle_range); + if (err_code != NRF_SUCCESS) { + return false; + } + + // Wait for a discovery event. + while (m_discovery_in_process) { + MICROPY_VM_HOOK_LOOP; + } + return m_discovery_successful; +} + +STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_connection_internal_t* connection) { + bleio_service_obj_t* tail = connection->remote_service_list; + + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_service_t *gattc_service = &response->services[i]; + + bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); + service->base.type = &bleio_service_type; + + // Initialize several fields at once. + bleio_service_from_connection(service, bleio_connection_new_from_internal(connection)); + + service->is_remote = true; + service->start_handle = gattc_service->handle_range.start_handle; + service->end_handle = gattc_service->handle_range.end_handle; + service->handle = gattc_service->handle_range.start_handle; + + if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known service UUID. + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid); + service->uuid = uuid; + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just set the UUID to NULL. + service->uuid = NULL; + } + + service->next = tail; + tail = service; + } + + connection->remote_service_list = tail; + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + +STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_connection_internal_t* connection) { + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_char_t *gattc_char = &response->chars[i]; + + bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); + characteristic->base.type = &bleio_characteristic_type; + + bleio_uuid_obj_t *uuid = NULL; + + if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known characteristic UUID. + uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid); + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just leave the UUID as NULL. + } + + bleio_characteristic_properties_t props = + (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) | + (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) | + (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) | + (gattc_char->char_props.read ? CHAR_PROP_READ : 0) | + (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) | + (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0); + + // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. + common_hal_bleio_characteristic_construct( + characteristic, m_char_discovery_service, gattc_char->handle_value, uuid, + props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, + GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc + NULL); + + mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + +STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio_connection_internal_t* connection) { + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_desc_t *gattc_desc = &response->descs[i]; + + // Remember handles for certain well-known descriptors. + switch (gattc_desc->uuid.uuid) { + case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: + m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle; + break; + + case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG: + m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle; + break; + + case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: + m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle; + break; + + default: + // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors, + // so ignore those. + // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors + break; + } + + bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t); + descriptor->base.type = &bleio_descriptor_type; + + bleio_uuid_obj_t *uuid = NULL; + + if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known descriptor UUID. + uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid); + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just leave the UUID as NULL. + } + + common_hal_bleio_descriptor_construct( + descriptor, m_desc_discovery_characteristic, uuid, + SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, + GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes); + descriptor->handle = gattc_desc->handle; + + mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor)); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + +STATIC bool discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t payload) { + bleio_connection_internal_t* connection = MP_OBJ_TO_PTR(payload); + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_DISCONNECTED: + m_discovery_successful = false; + m_discovery_in_process = false; + break; + + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, connection); + break; + + case BLE_GATTC_EVT_CHAR_DISC_RSP: + on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, connection); + break; + + case BLE_GATTC_EVT_DESC_DISC_RSP: + on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, connection); + break; + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id); + return false; + break; + } + return true; +} + +STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t service_uuids_whitelist) { + ble_drv_add_event_handler(discovery_on_ble_evt, self); + + // Start over with an empty list. + self->remote_service_list = NULL; + + if (service_uuids_whitelist == mp_const_none) { + // List of service UUID's not given, so discover all available services. + + uint16_t next_service_start_handle = BLE_GATT_HANDLE_START; + + while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) { + // discover_next_services() appends to remote_services_list. + + // Get the most recently discovered service, and then ask for services + // whose handles start after the last attribute handle inside that service. + const bleio_service_obj_t *service = self->remote_service_list; + next_service_start_handle = service->end_handle + 1; + } + } else { + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf); + mp_obj_t uuid_obj; + while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { + mp_raise_ValueError(translate("non-UUID found in service_uuids_whitelist")); + } + bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); + + ble_uuid_t nrf_uuid; + bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid); + + // Service might or might not be discovered; that's ok. Caller has to check + // Central.remote_services to find out. + // We only need to call this once for each service to discover. + discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid); + } + } + + + bleio_service_obj_t *service = self->remote_service_list; + while (service != NULL) { + // Skip the service if it had an unknown (unregistered) UUID. + if (service->uuid == NULL) { + service = service->next; + continue; + } + + uint16_t next_char_start_handle = service->start_handle; + + // Stop when we go past the end of the range of handles for this service or + // discovery call returns nothing. + // discover_next_characteristics() appends to the characteristic_list. + while (next_char_start_handle <= service->end_handle && + discover_next_characteristics(self, service, next_char_start_handle)) { + + + // Get the most recently discovered characteristic, and then ask for characteristics + // whose handles start after the last attribute handle inside that characteristic. + const bleio_characteristic_obj_t *characteristic = + MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]); + + next_char_start_handle = characteristic->handle + 1; + } + + // Got characteristics for this service. Now discover descriptors for each characteristic. + size_t char_list_len = service->characteristic_list->len; + for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) { + bleio_characteristic_obj_t *characteristic = + MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]); + const bool last_characteristic = char_idx == char_list_len - 1; + bleio_characteristic_obj_t *next_characteristic = last_characteristic + ? NULL + : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]); + + // Skip the characteristic if it had an unknown (unregistered) UUID. + if (characteristic->uuid == NULL) { + continue; + } + + uint16_t next_desc_start_handle = characteristic->handle + 1; + + // Don't run past the end of this service or the beginning of the next characteristic. + uint16_t next_desc_end_handle = next_characteristic == NULL + ? service->end_handle + : next_characteristic->handle - 1; + + // Stop when we go past the end of the range of handles for this service or + // discovery call returns nothing. + // discover_next_descriptors() appends to the descriptor_list. + while (next_desc_start_handle <= service->end_handle && + next_desc_start_handle < next_desc_end_handle && + discover_next_descriptors(self, characteristic, + next_desc_start_handle, next_desc_end_handle)) { + + // Get the most recently discovered descriptor, and then ask for descriptors + // whose handles start after that descriptor's handle. + const bleio_descriptor_obj_t *descriptor = characteristic->descriptor_list; + next_desc_start_handle = descriptor->handle + 1; + } + } + service = service->next; + } + + // This event handler is no longer needed. + ble_drv_remove_event_handler(discovery_on_ble_evt, self); + +} +mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) { + discover_remote_services(self->connection, service_uuids_whitelist); + // Convert to a tuple and then clear the list so the callee will take ownership. + mp_obj_tuple_t *services_tuple = service_linked_list_to_tuple(self->connection->remote_service_list); + self->connection->remote_service_list = NULL; + + return services_tuple; +} + + +uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) { + if (self == NULL || self->connection == NULL) { + return BLE_CONN_HANDLE_INVALID; + } + return self->connection->conn_handle; +} + +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* internal) { + if (internal->connection_obj != mp_const_none) { + return internal->connection_obj; + } + bleio_connection_obj_t *connection = m_new_obj(bleio_connection_obj_t); + connection->base.type = &bleio_connection_type; + connection->connection = internal; + internal->connection_obj = connection; + + return MP_OBJ_FROM_PTR(connection); +} diff --git a/ports/nrf/common-hal/_bleio/Peripheral.h b/ports/nrf/common-hal/_bleio/Connection.h similarity index 67% rename from ports/nrf/common-hal/_bleio/Peripheral.h rename to ports/nrf/common-hal/_bleio/Connection.h index a4f62d288a..2d4aad0c8d 100644 --- a/ports/nrf/common-hal/_bleio/Peripheral.h +++ b/ports/nrf/common-hal/_bleio/Connection.h @@ -25,8 +25,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H -#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H +#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CONNECTION_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CONNECTION_H #include @@ -37,6 +37,7 @@ #include "common-hal/_bleio/__init__.h" #include "shared-module/_bleio/Address.h" +#include "common-hal/_bleio/Service.h" typedef enum { PAIR_NOT_PAIRED, @@ -44,24 +45,35 @@ typedef enum { PAIR_PAIRED, } pair_status_t; +// We split the Connection object into two so that the internal mechanics can live outside of the +// VM. If it were one object, then we'd risk user code seeing a connection object of theirs be +// reused. typedef struct { - mp_obj_base_t base; - mp_obj_t name; - volatile uint16_t conn_handle; - // Services provided by this peripheral. - mp_obj_list_t *service_list; + uint16_t conn_handle; + bool is_central; // Remote services discovered when this peripheral is acting as a client. - mp_obj_list_t *remote_service_list; + bleio_service_obj_t *remote_service_list; // The advertising data and scan response buffers are held by us, not by the SD, so we must // maintain them and not change it. If we need to change the contents during advertising, // there are tricks to get the SD to notice (see DevZone - TBS). // EDIV: Encrypted Diversifier: Identifies LTK during legacy pairing. bonding_keys_t bonding_keys; uint16_t ediv; - uint8_t* advertising_data; - uint8_t* scan_response_data; - uint8_t adv_handle; pair_status_t pair_status; -} bleio_peripheral_obj_t; + mp_obj_t connection_obj; + ble_drv_evt_handler_entry_t handler_entry; +} bleio_connection_internal_t; -#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H +typedef struct { + mp_obj_base_t base; + bleio_connection_internal_t* connection; + // The HCI disconnect reason. + uint8_t disconnect_reason; +} bleio_connection_obj_t; + +bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in); + +uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* connection); + +#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CONNECTION_H diff --git a/ports/nrf/common-hal/_bleio/Descriptor.c b/ports/nrf/common-hal/_bleio/Descriptor.c index 137f004bab..faf50c658c 100644 --- a/ports/nrf/common-hal/_bleio/Descriptor.c +++ b/ports/nrf/common-hal/_bleio/Descriptor.c @@ -33,8 +33,6 @@ #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" -static volatile bleio_descriptor_obj_t *m_read_descriptor; - void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { self->characteristic = characteristic; self->uuid = uuid; @@ -61,62 +59,18 @@ bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio return self->characteristic; } -STATIC void descriptor_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { - switch (ble_evt->header.evt_id) { - - // More events may be handled later, so keep this as a switch. - - case BLE_GATTC_EVT_READ_RSP: { - ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; - if (m_read_descriptor) { - m_read_descriptor->value = mp_obj_new_bytearray(response->len, response->data); - } - // Indicate to busy-wait loop that we've read the attribute value. - m_read_descriptor = NULL; - break; - } - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled descriptor event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} - -STATIC void descriptor_gattc_read(bleio_descriptor_obj_t *descriptor) { - const uint16_t conn_handle = - common_hal_bleio_device_get_conn_handle(descriptor->characteristic->service->device); - common_hal_bleio_check_connected(conn_handle); - - // Set to NULL in event loop after event. - m_read_descriptor = descriptor; - - ble_drv_add_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor); - - const uint32_t err_code = sd_ble_gattc_read(conn_handle, descriptor->handle, 0); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code); - } - - while (m_read_descriptor != NULL) { - MICROPY_VM_HOOK_LOOP; - } - - ble_drv_remove_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor); -} - -mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self) { +size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len) { // Do GATT operations only if this descriptor has been registered if (self->handle != BLE_GATT_HANDLE_INVALID) { + uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - descriptor_gattc_read(self); + return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); } else { - self->value = common_hal_bleio_gatts_read( - self->handle, common_hal_bleio_device_get_conn_handle(self->characteristic->service->device)); + return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); } } - return self->value; + return 0; } void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) { @@ -131,7 +85,7 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff // Do GATT operations only if this descriptor has been registered. if (self->handle != BLE_GATT_HANDLE_INVALID) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->characteristic->service->device); + uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { // false means WRITE_REQ, not write-no-response common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); diff --git a/ports/nrf/common-hal/_bleio/Descriptor.h b/ports/nrf/common-hal/_bleio/Descriptor.h index 3adb0df184..c70547c08e 100644 --- a/ports/nrf/common-hal/_bleio/Descriptor.h +++ b/ports/nrf/common-hal/_bleio/Descriptor.h @@ -31,13 +31,15 @@ #include "py/obj.h" -#include "common-hal/_bleio/Characteristic.h" #include "common-hal/_bleio/UUID.h" -typedef struct { +// Forward declare characteristic because it includes a Descriptor. +struct _bleio_characteristic_obj; + +typedef struct _bleio_descriptor_obj { mp_obj_base_t base; // Will be MP_OBJ_NULL before being assigned to a Characteristic. - bleio_characteristic_obj_t *characteristic; + struct _bleio_characteristic_obj *characteristic; bleio_uuid_obj_t *uuid; mp_obj_t value; uint16_t max_length; @@ -45,6 +47,7 @@ typedef struct { uint16_t handle; bleio_attribute_security_mode_t read_perm; bleio_attribute_security_mode_t write_perm; + struct _bleio_descriptor_obj* next; } bleio_descriptor_obj_t; #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H diff --git a/ports/nrf/common-hal/_bleio/Peripheral.c b/ports/nrf/common-hal/_bleio/Peripheral.c deleted file mode 100644 index 9b0f96d48f..0000000000 --- a/ports/nrf/common-hal/_bleio/Peripheral.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Dan Halbert for Adafruit Industries - * 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 -#include - -#include "ble.h" -#include "ble_drv.h" -#include "ble_hci.h" -#include "nrf_soc.h" -#include "py/gc.h" -#include "py/objlist.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "shared-bindings/_bleio/__init__.h" -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Attribute.h" -#include "shared-bindings/_bleio/Characteristic.h" -#include "shared-bindings/_bleio/Peripheral.h" -#include "shared-bindings/_bleio/Service.h" -#include "shared-bindings/_bleio/UUID.h" - -#define BLE_ADV_LENGTH_FIELD_SIZE 1 -#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 -#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 - -static const ble_gap_sec_params_t pairing_sec_params = { - .bond = 1, - .mitm = 0, - .lesc = 0, - .keypress = 0, - .oob = 0, - .io_caps = BLE_GAP_IO_CAPS_NONE, - .min_key_size = 7, - .max_key_size = 16, - .kdist_own = { .enc = 1, .id = 1}, - .kdist_peer = { .enc = 1, .id = 1}, -}; - -STATIC void check_data_fit(size_t data_len) { - if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) { - mp_raise_ValueError(translate("Data too large for advertisement packet")); - } -} - -STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { - bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in; - - // For debugging. - // mp_printf(&mp_plat_print, "Peripheral event: 0x%04x\n", ble_evt->header.evt_id); - - switch (ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: { - // Central has connected. - ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected; - - self->conn_handle = ble_evt->evt.gap_evt.conn_handle; - - // See if connection interval set by Central is out of range. - // If so, negotiate our preferred range. - ble_gap_conn_params_t conn_params; - sd_ble_gap_ppcp_get(&conn_params); - if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval || - conn_params.min_conn_interval > connected->conn_params.max_conn_interval) { - sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); - } - break; - } - - case BLE_GAP_EVT_DISCONNECTED: - // Central has disconnected. - self->conn_handle = BLE_CONN_HANDLE_INVALID; - break; - - case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { - ble_gap_phys_t const phys = { - .rx_phys = BLE_GAP_PHY_AUTO, - .tx_phys = BLE_GAP_PHY_AUTO, - }; - sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys); - break; - } - - case BLE_GAP_EVT_ADV_SET_TERMINATED: - // TODO: Someday may handle timeouts or limit reached. - break; - - case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: - // SoftDevice will respond to a length update request. - sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL); - break; - - case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: { - // We only handle MTU of size BLE_GATT_ATT_MTU_DEFAULT. - sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATT_ATT_MTU_DEFAULT); - break; - } - - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); - break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { - ble_gap_sec_keyset_t keyset = { - .keys_own = { - .p_enc_key = &self->bonding_keys.own_enc, - .p_id_key = NULL, - .p_sign_key = NULL, - .p_pk = NULL - }, - - .keys_peer = { - .p_enc_key = &self->bonding_keys.peer_enc, - .p_id_key = &self->bonding_keys.peer_id, - .p_sign_key = NULL, - .p_pk = NULL - } - }; - - sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, - &pairing_sec_params, &keyset); - break; - } - - case BLE_GAP_EVT_LESC_DHKEY_REQUEST: - // TODO for LESC pairing: - // sd_ble_gap_lesc_dhkey_reply(...); - break; - - case BLE_GAP_EVT_AUTH_STATUS: { - // Pairing process completed - ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status; - if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status) { - // TODO _ediv = bonding_keys->own_enc.master_id.ediv; - self->pair_status = PAIR_PAIRED; - } else { - self->pair_status = PAIR_NOT_PAIRED; - } - break; - } - - case BLE_GAP_EVT_SEC_INFO_REQUEST: { - // Peer asks for the stored keys. - // - load key and return if bonded previously. - // - Else return NULL --> Initiate key exchange - ble_gap_evt_sec_info_request_t* sec_info_request = &ble_evt->evt.gap_evt.params.sec_info_request; - (void) sec_info_request; - //if ( bond_load_keys(_role, sec_req->master_id.ediv, &bkeys) ) { - //sd_ble_gap_sec_info_reply(_conn_hdl, &bkeys.own_enc.enc_info, &bkeys.peer_id.id_info, NULL); - // - //_ediv = bkeys.own_enc.master_id.ediv; - // } else { - sd_ble_gap_sec_info_reply(self->conn_handle, NULL, NULL, NULL); - // } - break; - } - - case BLE_GAP_EVT_CONN_SEC_UPDATE: { - ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec; - if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) { - // Security setup did not succeed: - // mode 0, level 0 means no access - // mode 1, level 1 means open link - // mode >=1 and/or level >=1 means encryption is set up - self->pair_status = PAIR_NOT_PAIRED; - } else { - //if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) { - if (true) { // TODO: no bonding yet - // Initialize system attributes fresh. - sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); - } - // Not quite paired yet: wait for BLE_GAP_EVT_AUTH_STATUS SUCCESS. - self->ediv = self->bonding_keys.own_enc.master_id.ediv; - } - break; - } - - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} - -void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_t name) { - common_hal_bleio_adapter_set_enabled(true); - - self->service_list = mp_obj_new_list(0, NULL); - // Used only for discovery when acting as a client. - self->remote_service_list = mp_obj_new_list(0, NULL); - self->name = name; - - self->conn_handle = BLE_CONN_HANDLE_INVALID; - self->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; - self->pair_status = PAIR_NOT_PAIRED; - - memset(&self->bonding_keys, 0, sizeof(self->bonding_keys)); -} - -void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service) { - ble_uuid_t uuid; - bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid); - - uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; - if (common_hal_bleio_service_get_is_secondary(service)) { - service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; - } - - const uint32_t err_code = sd_ble_gatts_service_add(service_type, &uuid, &service->handle); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to add service, err 0x%04x"), err_code); - } - - mp_obj_list_append(self->service_list, MP_OBJ_FROM_PTR(service)); -} - -mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self) { - return self->service_list; -} - -bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self) { - return self->conn_handle != BLE_CONN_HANDLE_INVALID; -} - -mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self) { - return self->name; -} - -void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) { - - // interval value has already been validated. - - if (connectable) { - ble_drv_add_event_handler(peripheral_on_ble_evt, self); - } - - common_hal_bleio_adapter_set_enabled(true); - - uint32_t err_code; - - GET_STR_DATA_LEN(self->name, name_data, name_len); - if (name_len > 0) { - // Set device name, and make it available to anyone. - ble_gap_conn_sec_mode_t sec_mode; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - err_code = sd_ble_gap_device_name_set(&sec_mode, name_data, name_len); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to set device name, err 0x%04x"), err_code); - - } - } - - check_data_fit(advertising_data_bufinfo->len); - // The advertising data buffers must not move, because the SoftDevice depends on them. - // So make them long-lived. - self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true); - memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len); - - check_data_fit(scan_response_data_bufinfo->len); - self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true); - memcpy(self->scan_response_data, scan_response_data_bufinfo->buf, scan_response_data_bufinfo->len); - - - ble_gap_adv_params_t adv_params = { - .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), - .properties.type = connectable ? BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED - : BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED, - .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED, - .filter_policy = BLE_GAP_ADV_FP_ANY, - .primary_phy = BLE_GAP_PHY_1MBPS, - }; - - common_hal_bleio_peripheral_stop_advertising(self); - - const ble_gap_adv_data_t ble_gap_adv_data = { - .adv_data.p_data = self->advertising_data, - .adv_data.len = advertising_data_bufinfo->len, - .scan_rsp_data.p_data = scan_response_data_bufinfo-> len > 0 ? self->scan_response_data : NULL, - .scan_rsp_data.len = scan_response_data_bufinfo->len, - }; - - err_code = sd_ble_gap_adv_set_configure(&self->adv_handle, &ble_gap_adv_data, &adv_params); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to configure advertising, err 0x%04x"), err_code); - } - - err_code = sd_ble_gap_adv_start(self->adv_handle, BLE_CONN_CFG_TAG_CUSTOM); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to start advertising, err 0x%04x"), err_code); - } -} - -void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self) { - if (self->adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) - return; - - const uint32_t err_code = sd_ble_gap_adv_stop(self->adv_handle); - - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) { - mp_raise_OSError_msg_varg(translate("Failed to stop advertising, err 0x%04x"), err_code); - } -} - -void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *self) { - sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); -} - -mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist) { - common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist); - // Convert to a tuple and then clear the list so the callee will take ownership. - mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_service_list->len, - self->remote_service_list->items); - mp_obj_list_clear(self->remote_service_list); - return services_tuple; -} - -void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *self) { - self->pair_status = PAIR_WAITING; - - uint32_t err_code = sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to start pairing, error 0x%04x"), err_code); - } - - while (self->pair_status == PAIR_WAITING) { - RUN_BACKGROUND_TASKS; - } - - if (self->pair_status == PAIR_NOT_PAIRED) { - mp_raise_OSError_msg(translate("Failed to pair")); - } - - -} diff --git a/ports/nrf/common-hal/_bleio/Scanner.c b/ports/nrf/common-hal/_bleio/Scanner.c deleted file mode 100644 index ec73f7eb8f..0000000000 --- a/ports/nrf/common-hal/_bleio/Scanner.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * Copyright (c) 2016 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 - -#include "ble_drv.h" -#include "ble_gap.h" -#include "py/mphal.h" -#include "py/objlist.h" -#include "py/runtime.h" -#include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/ScanEntry.h" -#include "shared-bindings/_bleio/Scanner.h" -#include "shared-module/_bleio/ScanEntry.h" - -static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; - -static ble_data_t m_scan_buffer = { - m_scan_buffer_data, - BLE_GAP_SCAN_BUFFER_MIN -}; - -STATIC void scanner_on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) { - bleio_scanner_obj_t *scanner = (bleio_scanner_obj_t*)scanner_in; - ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; - - if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) { - return; - } - - bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t); - entry->base.type = &bleio_scanentry_type; - entry->rssi = report->rssi; - - bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); - address->base.type = &bleio_address_type; - common_hal_bleio_address_construct(MP_OBJ_TO_PTR(address), - report->peer_addr.addr, report->peer_addr.addr_type); - entry->address = address; - - entry->data = mp_obj_new_bytes(report->data.p_data, report->data.len); - - mp_obj_list_append(scanner->scan_entries, MP_OBJ_FROM_PTR(entry)); - - const uint32_t err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to continue scanning, err 0x%04x"), err_code); - } -} - -void common_hal_bleio_scanner_construct(bleio_scanner_obj_t *self) { -} - -mp_obj_t common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_float_t timeout, mp_float_t interval, mp_float_t window) { - common_hal_bleio_adapter_set_enabled(true); - ble_drv_add_event_handler(scanner_on_ble_evt, self); - - ble_gap_scan_params_t scan_params = { - .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), - .window = SEC_TO_UNITS(window, UNIT_0_625_MS), - .scan_phys = BLE_GAP_PHY_1MBPS, - }; - - self->scan_entries = mp_obj_new_list(0, NULL); - - uint32_t err_code; - err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to start scanning, err 0x%04x"), err_code); - } - - mp_hal_delay_ms(timeout * 1000); - sd_ble_gap_scan_stop(); - - // Return list, and don't hang on to it, so it can be GC'd. - mp_obj_t entries = self->scan_entries; - self->scan_entries = MP_OBJ_NULL; - return entries; -} diff --git a/ports/nrf/common-hal/_bleio/Service.c b/ports/nrf/common-hal/_bleio/Service.c index 650cdc4ec9..3362ed1373 100644 --- a/ports/nrf/common-hal/_bleio/Service.c +++ b/ports/nrf/common-hal/_bleio/Service.c @@ -31,17 +31,44 @@ #include "common-hal/_bleio/__init__.h" #include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/Descriptor.h" -#include "shared-bindings/_bleio/Peripheral.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/Adapter.h" -void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_peripheral_obj_t *peripheral, bleio_uuid_obj_t *uuid, bool is_secondary) { - self->device = MP_OBJ_FROM_PTR(peripheral); +uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list) { self->handle = 0xFFFF; self->uuid = uuid; - self->characteristic_list = mp_obj_new_list(0, NULL); + self->characteristic_list = characteristic_list; self->is_remote = false; + self->connection = NULL; self->is_secondary = is_secondary; + + ble_uuid_t nordic_uuid; + bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nordic_uuid); + + uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; + if (is_secondary) { + service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; + } + + vm_used_ble = true; + + return sd_ble_gatts_service_add(service_type, &nordic_uuid, &self->handle); +} + +void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) { + const uint32_t err_code = _common_hal_bleio_service_construct(self, uuid, is_secondary, mp_obj_new_list(0, NULL)); + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to create service, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); + } +} + +void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) { + self->handle = 0xFFFF; + self->uuid = NULL; + self->characteristic_list = mp_obj_new_list(0, NULL); + self->is_remote = true; + self->is_secondary = false; + self->connection = connection; } bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) { @@ -60,7 +87,9 @@ bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) { return self->is_secondary; } -void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic) { +void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_buffer_info_t *initial_value_bufinfo) { ble_gatts_char_md_t char_md = { .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0, .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0, @@ -93,14 +122,11 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, blei bleio_attribute_gatts_set_security_mode(&char_attr_md.read_perm, characteristic->read_perm); bleio_attribute_gatts_set_security_mode(&char_attr_md.write_perm, characteristic->write_perm); - mp_buffer_info_t char_value_bufinfo; - mp_get_buffer_raise(characteristic->value, &char_value_bufinfo, MP_BUFFER_READ); - ble_gatts_attr_t char_attr = { .p_uuid = &char_uuid, .p_attr_md = &char_attr_md, - .init_len = char_value_bufinfo.len, - .p_value = char_value_bufinfo.buf, + .init_len = 0, + .p_value = NULL, .init_offs = 0, .max_len = characteristic->max_length, }; @@ -110,7 +136,7 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, blei uint32_t err_code; err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &char_attr, &char_handles); if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to add characteristic, err 0x%04x"), err_code); + mp_raise_OSError_msg_varg(translate("Failed to add characteristic, NRF_ERROR_%q"), MP_OBJ_QSTR_VALUE(base_error_messages[err_code - NRF_ERROR_BASE_NUM])); } characteristic->user_desc_handle = char_handles.user_desc_handle; diff --git a/ports/nrf/common-hal/_bleio/Service.h b/ports/nrf/common-hal/_bleio/Service.h index a4614b9f51..f101bc825b 100644 --- a/ports/nrf/common-hal/_bleio/Service.h +++ b/ports/nrf/common-hal/_bleio/Service.h @@ -31,20 +31,22 @@ #include "py/objlist.h" #include "common-hal/_bleio/UUID.h" -typedef struct { +typedef struct bleio_service_obj { mp_obj_base_t base; - // Handle for this service. + // Handle for the local service. uint16_t handle; // True if created during discovery. bool is_remote; bool is_secondary; bleio_uuid_obj_t *uuid; - // May be a Peripheral, Central, etc. - mp_obj_t device; + mp_obj_t connection; mp_obj_list_t *characteristic_list; - // Range of attribute handles of this service. + // Range of attribute handles of this remote service. uint16_t start_handle; uint16_t end_handle; + struct bleio_service_obj* next; } bleio_service_obj_t; +void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection); + #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SERVICE_H diff --git a/ports/nrf/common-hal/_bleio/UUID.c b/ports/nrf/common-hal/_bleio/UUID.c index 0e65b7d58d..5bf35e6a54 100644 --- a/ports/nrf/common-hal/_bleio/UUID.c +++ b/ports/nrf/common-hal/_bleio/UUID.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "common-hal/_bleio/UUID.h" +#include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" #include "ble.h" @@ -39,9 +40,7 @@ // If uuid128 is NULL, this is a Bluetooth SIG 16-bit UUID. // If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where // the 16-bit part goes. Those 16 bits are passed in uuid16. -void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, uint8_t uuid128[]) { - common_hal_bleio_adapter_set_enabled(true); - +void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, const uint8_t uuid128[]) { self->nrf_ble_uuid.uuid = uuid16; if (uuid128 == NULL) { self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE; @@ -54,6 +53,7 @@ void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, ui if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg_varg(translate("Failed to register Vendor-Specific UUID, err 0x%04x"), err_code); } + vm_used_ble = true; } } @@ -65,25 +65,24 @@ uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) { return self->nrf_ble_uuid.uuid; } -// True if uuid128 has been successfully filled in. -bool common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { +void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { uint8_t length; const uint32_t err_code = sd_ble_uuid_encode(&self->nrf_ble_uuid, &length, uuid128); if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg_varg(translate("Could not decode ble_uuid, err 0x%04x"), err_code); } - // If not 16 bytes, this is not a 128-bit UUID, so return. - return length == 16; } -// Returns 0 if this is a 16-bit UUID, otherwise returns a non-zero index -// into the 128-bit uuid registration table. -uint32_t common_hal_bleio_uuid_get_uuid128_reference(bleio_uuid_obj_t *self) { - return self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE ? 0 : self->nrf_ble_uuid.type; +void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf) { + if (self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE) { + buf[0] = self->nrf_ble_uuid.uuid & 0xff; + buf[1] = self->nrf_ble_uuid.uuid >> 8; + } else { + common_hal_bleio_uuid_get_uuid128(self, buf); + } } - void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_ble_uuid) { if (nrf_ble_uuid->type == BLE_UUID_TYPE_UNKNOWN) { mp_raise_RuntimeError(translate("Unexpected nrfx uuid type")); diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c index 5530441909..1e07ea969c 100644 --- a/ports/nrf/common-hal/_bleio/__init__.c +++ b/ports/nrf/common-hal/_bleio/__init__.c @@ -26,34 +26,58 @@ * THE SOFTWARE. */ +#include + #include "py/runtime.h" #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" -#include "shared-bindings/_bleio/Central.h" #include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Connection.h" #include "shared-bindings/_bleio/Descriptor.h" -#include "shared-bindings/_bleio/Peripheral.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" +#include "supervisor/shared/bluetooth.h" #include "common-hal/_bleio/__init__.h" -static volatile bool m_discovery_in_process; -static volatile bool m_discovery_successful; - -static bleio_service_obj_t *m_char_discovery_service; -static bleio_characteristic_obj_t *m_desc_discovery_characteristic; +const mp_obj_t base_error_messages[20] = { + MP_ROM_QSTR(MP_QSTR_SUCCESS), + MP_ROM_QSTR(MP_QSTR_SVC_HANDLER_MISSING), + MP_ROM_QSTR(MP_QSTR_SOFTDEVICE_NOT_ENABLED), + MP_ROM_QSTR(MP_QSTR_INTERNAL), + MP_ROM_QSTR(MP_QSTR_NO_MEM), + MP_ROM_QSTR(MP_QSTR_NOT_FOUND), + MP_ROM_QSTR(MP_QSTR_NOT_SUPPORTED), + MP_ROM_QSTR(MP_QSTR_INVALID_PARAM), + MP_ROM_QSTR(MP_QSTR_INVALID_STATE), + MP_ROM_QSTR(MP_QSTR_INVALID_LENGTH), + MP_ROM_QSTR(MP_QSTR_INVALID_FLAGS), + MP_ROM_QSTR(MP_QSTR_INVALID_DATA), + MP_ROM_QSTR(MP_QSTR_DATA_SIZE), + MP_ROM_QSTR(MP_QSTR_TIMEOUT), + MP_ROM_QSTR(MP_QSTR_NULL), + MP_ROM_QSTR(MP_QSTR_FORBIDDEN), + MP_ROM_QSTR(MP_QSTR_INVALID_ADDR), + MP_ROM_QSTR(MP_QSTR_BUSY), + MP_ROM_QSTR(MP_QSTR_CONN_COUNT), + MP_ROM_QSTR(MP_QSTR_RESOURCES), +}; // Turn off BLE on a reset or reload. void bleio_reset() { - if (common_hal_bleio_adapter_get_enabled()) { - common_hal_bleio_adapter_set_enabled(false); + bleio_adapter_reset(&common_hal_bleio_adapter_obj); + if (!vm_used_ble) { + return; } + if (common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false); + } + supervisor_start_bluetooth(); } // The singleton _bleio.Adapter object, bound to _bleio.adapter // It currently only has properties and no state -const super_adapter_obj_t common_hal_bleio_adapter_obj = { +bleio_adapter_obj_t common_hal_bleio_adapter_obj = { .base = { .type = &bleio_adapter_type, }, @@ -65,395 +89,22 @@ void common_hal_bleio_check_connected(uint16_t conn_handle) { } } -uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) { - if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { - return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle; - } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) { - return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle; - } else { - return BLE_CONN_HANDLE_INVALID; - } -} - -mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device) { - if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { - return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->remote_service_list; - } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) { - return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->remote_service_list; - } else { - return NULL; - } -} - -// service_uuid may be NULL, to discover all services. -STATIC bool discover_next_services(mp_obj_t device, uint16_t start_handle, ble_uuid_t *service_uuid) { - m_discovery_successful = false; - m_discovery_in_process = true; - - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); - uint32_t err_code = sd_ble_gattc_primary_services_discover(conn_handle, start_handle, service_uuid); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg(translate("Failed to discover services")); - } - - // Wait for a discovery event. - while (m_discovery_in_process) { - MICROPY_VM_HOOK_LOOP; - } - return m_discovery_successful; -} - -STATIC bool discover_next_characteristics(mp_obj_t device, bleio_service_obj_t *service, uint16_t start_handle) { - m_char_discovery_service = service; - - ble_gattc_handle_range_t handle_range; - handle_range.start_handle = start_handle; - handle_range.end_handle = service->end_handle; - - m_discovery_successful = false; - m_discovery_in_process = true; - - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); - uint32_t err_code = sd_ble_gattc_characteristics_discover(conn_handle, &handle_range); - if (err_code != NRF_SUCCESS) { - return false; - } - - // Wait for a discovery event. - while (m_discovery_in_process) { - MICROPY_VM_HOOK_LOOP; - } - return m_discovery_successful; -} - -STATIC bool discover_next_descriptors(mp_obj_t device, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) { - m_desc_discovery_characteristic = characteristic; - - ble_gattc_handle_range_t handle_range; - handle_range.start_handle = start_handle; - handle_range.end_handle = end_handle; - - m_discovery_successful = false; - m_discovery_in_process = true; - - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); - uint32_t err_code = sd_ble_gattc_descriptors_discover(conn_handle, &handle_range); - if (err_code != NRF_SUCCESS) { - return false; - } - - // Wait for a discovery event. - while (m_discovery_in_process) { - MICROPY_VM_HOOK_LOOP; - } - return m_discovery_successful; -} - -STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, mp_obj_t device) { - for (size_t i = 0; i < response->count; ++i) { - ble_gattc_service_t *gattc_service = &response->services[i]; - - bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); - service->base.type = &bleio_service_type; - - // Initialize several fields at once. - common_hal_bleio_service_construct(service, device, NULL, false); - - service->is_remote = true; - service->start_handle = gattc_service->handle_range.start_handle; - service->end_handle = gattc_service->handle_range.end_handle; - service->handle = gattc_service->handle_range.start_handle; - - if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) { - // Known service UUID. - bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid); - service->uuid = uuid; - } else { - // The discovery response contained a 128-bit UUID that has not yet been registered with the - // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. - // For now, just set the UUID to NULL. - service->uuid = NULL; - } - - mp_obj_list_append(common_hal_bleio_device_get_remote_service_list(device), service); - } - - if (response->count > 0) { - m_discovery_successful = true; - } - m_discovery_in_process = false; -} - -STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_obj_t device) { - for (size_t i = 0; i < response->count; ++i) { - ble_gattc_char_t *gattc_char = &response->chars[i]; - - bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); - characteristic->base.type = &bleio_characteristic_type; - - bleio_uuid_obj_t *uuid = NULL; - - if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) { - // Known characteristic UUID. - uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid); - } else { - // The discovery response contained a 128-bit UUID that has not yet been registered with the - // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. - // For now, just leave the UUID as NULL. - } - - bleio_characteristic_properties_t props = - (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) | - (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) | - (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) | - (gattc_char->char_props.read ? CHAR_PROP_READ : 0) | - (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) | - (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0); - - // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. - common_hal_bleio_characteristic_construct( - characteristic, m_char_discovery_service, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, - GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc - mp_obj_new_list(0, NULL)); - characteristic->handle = gattc_char->handle_value; - - mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); - } - - if (response->count > 0) { - m_discovery_successful = true; - } - m_discovery_in_process = false; -} - -STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_obj_t device) { - for (size_t i = 0; i < response->count; ++i) { - ble_gattc_desc_t *gattc_desc = &response->descs[i]; - - // Remember handles for certain well-known descriptors. - switch (gattc_desc->uuid.uuid) { - case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: - m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle; - break; - - case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG: - m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle; - break; - - case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: - m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle; - break; - - default: - // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors, - // so ignore those. - // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors - break; - } - - bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t); - descriptor->base.type = &bleio_descriptor_type; - - bleio_uuid_obj_t *uuid = NULL; - - if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) { - // Known descriptor UUID. - uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid); - } else { - // The discovery response contained a 128-bit UUID that has not yet been registered with the - // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. - // For now, just leave the UUID as NULL. - } - - common_hal_bleio_descriptor_construct( - descriptor, m_desc_discovery_characteristic, uuid, - SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, - GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes); - descriptor->handle = gattc_desc->handle; - - mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor)); - } - - if (response->count > 0) { - m_discovery_successful = true; - } - m_discovery_in_process = false; -} - -STATIC void discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t device) { - switch (ble_evt->header.evt_id) { - case BLE_GAP_EVT_DISCONNECTED: - m_discovery_successful = false; - m_discovery_in_process = false; - break; - - case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: - on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, device); - break; - - case BLE_GATTC_EVT_CHAR_DISC_RSP: - on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, device); - break; - - case BLE_GATTC_EVT_DESC_DISC_RSP: - on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, device); - break; - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id); - break; - } -} - - -void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist) { - mp_obj_list_t *remote_services_list = common_hal_bleio_device_get_remote_service_list(device); - - ble_drv_add_event_handler(discovery_on_ble_evt, device); - - // Start over with an empty list. - mp_obj_list_clear(MP_OBJ_FROM_PTR(common_hal_bleio_device_get_remote_service_list(device))); - - if (service_uuids_whitelist == mp_const_none) { - // List of service UUID's not given, so discover all available services. - - uint16_t next_service_start_handle = BLE_GATT_HANDLE_START; - - while (discover_next_services(device, next_service_start_handle, MP_OBJ_NULL)) { - // discover_next_services() appends to remote_services_list. - - // Get the most recently discovered service, and then ask for services - // whose handles start after the last attribute handle inside that service. - const bleio_service_obj_t *service = - MP_OBJ_TO_PTR(remote_services_list->items[remote_services_list->len - 1]); - next_service_start_handle = service->end_handle + 1; - } - } else { - mp_obj_iter_buf_t iter_buf; - mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf); - mp_obj_t uuid_obj; - while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { - mp_raise_ValueError(translate("non-UUID found in service_uuids_whitelist")); - } - bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); - - ble_uuid_t nrf_uuid; - bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid); - - // Service might or might not be discovered; that's ok. Caller has to check - // Central.remote_services to find out. - // We only need to call this once for each service to discover. - discover_next_services(device, BLE_GATT_HANDLE_START, &nrf_uuid); - } - } - - - for (size_t service_idx = 0; service_idx < remote_services_list->len; ++service_idx) { - bleio_service_obj_t *service = MP_OBJ_TO_PTR(remote_services_list->items[service_idx]); - - // Skip the service if it had an unknown (unregistered) UUID. - if (service->uuid == NULL) { - continue; - } - - uint16_t next_char_start_handle = service->start_handle; - - // Stop when we go past the end of the range of handles for this service or - // discovery call returns nothing. - // discover_next_characteristics() appends to the characteristic_list. - while (next_char_start_handle <= service->end_handle && - discover_next_characteristics(device, service, next_char_start_handle)) { - - - // Get the most recently discovered characteristic, and then ask for characteristics - // whose handles start after the last attribute handle inside that characteristic. - const bleio_characteristic_obj_t *characteristic = - MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]); - next_char_start_handle = characteristic->handle + 1; - } - - // Got characteristics for this service. Now discover descriptors for each characteristic. - size_t char_list_len = service->characteristic_list->len; - for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) { - bleio_characteristic_obj_t *characteristic = - MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]); - const bool last_characteristic = char_idx == char_list_len - 1; - bleio_characteristic_obj_t *next_characteristic = last_characteristic - ? NULL - : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]); - - // Skip the characteristic if it had an unknown (unregistered) UUID. - if (characteristic->uuid == NULL) { - continue; - } - - uint16_t next_desc_start_handle = characteristic->handle + 1; - - // Don't run past the end of this service or the beginning of the next characteristic. - uint16_t next_desc_end_handle = next_characteristic == NULL - ? service->end_handle - : next_characteristic->handle - 1; - - // Stop when we go past the end of the range of handles for this service or - // discovery call returns nothing. - // discover_next_descriptors() appends to the descriptor_list. - while (next_desc_start_handle <= service->end_handle && - next_desc_start_handle < next_desc_end_handle && - discover_next_descriptors(device, characteristic, - next_desc_start_handle, next_desc_end_handle)) { - - // Get the most recently discovered descriptor, and then ask for descriptors - // whose handles start after that descriptor's handle. - const bleio_descriptor_obj_t *descriptor = - MP_OBJ_TO_PTR(characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1]); - next_desc_start_handle = descriptor->handle + 1; - } - } - } - - // This event handler is no longer needed. - ble_drv_remove_event_handler(discovery_on_ble_evt, device); - -} - // GATTS read of a Characteristic or Descriptor. -mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle) { +size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) { // conn_handle might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because // we can still read and write the local value. - mp_buffer_info_t bufinfo; ble_gatts_value_t gatts_value = { - .p_value = NULL, - .len = 0, + .p_value = buf, + .len = len, }; - // Read once to find out what size buffer we need, then read again to fill buffer. - - mp_obj_t value = mp_const_none; uint32_t err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value); - if (err_code == NRF_SUCCESS) { - value = mp_obj_new_bytearray_of_zeros(gatts_value.len); - mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_WRITE); - gatts_value.p_value = bufinfo.buf; - - // Read again, with the correct size of buffer. - err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value); - } - if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code); } - return value; + return gatts_value.len; } void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { @@ -471,6 +122,72 @@ void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buff } } +typedef struct { + uint8_t* buf; + size_t len; + size_t final_len; + uint16_t conn_handle; + volatile uint16_t status; + volatile bool done; +} read_info_t; + +STATIC bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { + read_info_t* read = param; + switch (ble_evt->header.evt_id) { + + // More events may be handled later, so keep this as a switch. + + case BLE_GATTC_EVT_READ_RSP: { + ble_gattc_evt_t* evt = &ble_evt->evt.gattc_evt; + ble_gattc_evt_read_rsp_t *response = &evt->params.read_rsp; + if (read && evt->conn_handle == read->conn_handle) { + read->status = evt->gatt_status; + size_t len = MIN(read->len, response->len); + memcpy(read->buf, response->data, len); + read->final_len = len; + // Indicate to busy-wait loop that we've read the attribute value. + read->done = true; + } + break; + } + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); + return false; + break; + } + return true; +} + +size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) { + common_hal_bleio_check_connected(conn_handle); + + read_info_t read_info; + read_info.buf = buf; + read_info.len = len; + read_info.final_len = 0; + read_info.conn_handle = conn_handle; + // Set to true by the event handler. + read_info.done = false; + ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info); + + const uint32_t err_code = sd_ble_gattc_read(conn_handle, handle, 0); + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed initiate attribute read, err 0x%04x"), err_code); + } + + while (!read_info.done) { + RUN_BACKGROUND_TASKS; + } + if (read_info.status != BLE_GATT_STATUS_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), read_info.status); + } + + ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info); + return read_info.final_len; +} + void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { common_hal_bleio_check_connected(conn_handle); @@ -500,3 +217,7 @@ void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buff } } + +void common_hal_bleio_gc_collect(void) { + bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj); +} diff --git a/ports/nrf/common-hal/_bleio/__init__.h b/ports/nrf/common-hal/_bleio/__init__.h index cf1a06945d..5fd2769f26 100644 --- a/ports/nrf/common-hal/_bleio/__init__.h +++ b/ports/nrf/common-hal/_bleio/__init__.h @@ -39,4 +39,9 @@ typedef struct { // 20 bytes max (23 - 3). #define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3) +const mp_obj_t base_error_messages[20]; + +// Track if the user code modified the BLE state to know if we need to undo it on reload. +bool vm_used_ble; + #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H diff --git a/ports/stm32f4/boards/feather_stm32f405_express/pins.c b/ports/stm32f4/boards/feather_stm32f405_express/pins.c index 518ab6d2a0..4aa1f362ad 100644 --- a/ports/stm32f4/boards/feather_stm32f405_express/pins.c +++ b/ports/stm32f4/boards/feather_stm32f405_express/pins.c @@ -25,5 +25,9 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB10) }, { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB11) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/stm32f4/boards/feather_stm32f405_express/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/feather_stm32f405_express/stm32f4xx_hal_conf.h index a13e5ecfa3..7a1a9428f8 100644 --- a/ports/stm32f4/boards/feather_stm32f405_express/stm32f4xx_hal_conf.h +++ b/ports/stm32f4/boards/feather_stm32f405_express/stm32f4xx_hal_conf.h @@ -61,7 +61,7 @@ /* #define HAL_SD_MODULE_ENABLED */ /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ diff --git a/ports/stm32f4/boards/pyboard_v11/mpconfigboard.h b/ports/stm32f4/boards/pyboard_v11/mpconfigboard.h index e8441d665c..9d8f72f77c 100644 --- a/ports/stm32f4/boards/pyboard_v11/mpconfigboard.h +++ b/ports/stm32f4/boards/pyboard_v11/mpconfigboard.h @@ -3,8 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2016 Glenn Ruben Bakke - * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland 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 @@ -34,4 +33,7 @@ #define FLASH_PAGE_SIZE (0x4000) #define AUTORESET_DELAY_MS 500 -#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000) \ No newline at end of file +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000) + +#define DEFAULT_I2C_BUS_SCL (&pin_PB06) +#define DEFAULT_I2C_BUS_SDA (&pin_PB07) diff --git a/ports/stm32f4/boards/pyboard_v11/pins.c b/ports/stm32f4/boards/pyboard_v11/pins.c index ccbb58ab9e..8783dfcf10 100644 --- a/ports/stm32f4/boards/pyboard_v11/pins.c +++ b/ports/stm32f4/boards/pyboard_v11/pins.c @@ -46,5 +46,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB06) }, { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB07) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h index a13e5ecfa3..7a1a9428f8 100644 --- a/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h +++ b/ports/stm32f4/boards/pyboard_v11/stm32f4xx_hal_conf.h @@ -61,7 +61,7 @@ /* #define HAL_SD_MODULE_ENABLED */ /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ diff --git a/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h b/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h index d5491fe362..d7898ba0b8 100644 --- a/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h +++ b/ports/stm32f4/boards/stm32f411ve_discovery/mpconfigboard.h @@ -3,8 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2016 Glenn Ruben Bakke - * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland 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 diff --git a/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h index b244a69b5e..18d9d60ebe 100644 --- a/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h +++ b/ports/stm32f4/boards/stm32f411ve_discovery/stm32f4xx_hal_conf.h @@ -61,7 +61,7 @@ /* #define HAL_SD_MODULE_ENABLED */ /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.h b/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.h index ebee98f89f..d01d0dd9fd 100644 --- a/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.h +++ b/ports/stm32f4/boards/stm32f412zg_discovery/mpconfigboard.h @@ -3,8 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2016 Glenn Ruben Bakke - * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2019 Lucian Copeland 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 diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/pins.c b/ports/stm32f4/boards/stm32f412zg_discovery/pins.c index a0b477a470..b92f212700 100644 --- a/ports/stm32f4/boards/stm32f412zg_discovery/pins.c +++ b/ports/stm32f4/boards/stm32f412zg_discovery/pins.c @@ -88,5 +88,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_PE01) }, { MP_ROM_QSTR(MP_QSTR_LED3), MP_ROM_PTR(&pin_PE02) }, { MP_ROM_QSTR(MP_QSTR_LED4), MP_ROM_PTR(&pin_PE03) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h b/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h index 2ad0fee20b..b89240f982 100644 --- a/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h +++ b/ports/stm32f4/boards/stm32f412zg_discovery/stm32f4xx_hal_conf.h @@ -61,7 +61,7 @@ #define HAL_SD_MODULE_ENABLED /* #define HAL_MMC_MODULE_ENABLED */ #define HAL_SPI_MODULE_ENABLED -/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED /* #define HAL_USART_MODULE_ENABLED */ /* #define HAL_IRDA_MODULE_ENABLED */ diff --git a/ports/stm32f4/common-hal/pulseio/PWMOut.c b/ports/stm32f4/common-hal/pulseio/PWMOut.c new file mode 100644 index 0000000000..16b1b5b896 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.c @@ -0,0 +1,399 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Lucian Copeland for Adafruit Industries + * Uses code from Micropython, Copyright (c) 2013-2016 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 +#include "py/runtime.h" +#include "common-hal/pulseio/PWMOut.h" +#include "shared-bindings/pulseio/PWMOut.h" +#include "supervisor/shared/translate.h" + +#include "shared-bindings/microcontroller/__init__.h" +#include "stm32f4xx_hal.h" +#include "common-hal/microcontroller/Pin.h" + +#define ALL_CLOCKS 0xFFFF + +STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN]; +STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN]; +STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN]; + +STATIC void tim_clock_enable(uint16_t mask); +STATIC void tim_clock_disable(uint16_t mask); + +// Get the frequency (in Hz) of the source clock for the given timer. +// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set. +// If the APB prescaler is 1, then the timer clock is equal to its respective +// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its +// respective APB clock. See DM00031020 Rev 4, page 115. +STATIC uint32_t timer_get_source_freq(uint32_t tim_id) { + uint32_t source, clk_div; + if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) { + // TIM{1,8,9,10,11} are on APB2 + source = HAL_RCC_GetPCLK2Freq(); + clk_div = RCC->CFGR & RCC_CFGR_PPRE2; + } else { + // TIM{2,3,4,5,6,7,12,13,14} are on APB1 + source = HAL_RCC_GetPCLK1Freq(); + clk_div = RCC->CFGR & RCC_CFGR_PPRE1; + } + if (clk_div != 0) { + // APB prescaler for this timer is > 1 + source *= 2; + } + return source; +} + +STATIC uint32_t timer_get_internal_duty(uint16_t duty, uint32_t period) { + //duty cycle is duty/0xFFFF fraction x (number of pulses per period) + return (duty*period)/((1<<16)-1); +} + +STATIC void timer_get_optimal_divisors(uint32_t*period, uint32_t*prescaler, + uint32_t frequency, uint32_t source_freq) { + //Find the largest possible period supported by this frequency + for (int i=0; i<(1 << 16);i++) { + *period = source_freq/(i*frequency); + if (*period < (1 << 16) && *period>=2) { + *prescaler = i; + break; + } + } + if (*prescaler == 0) { + mp_raise_ValueError(translate("Invalid frequency supplied")); + } +} + +void pwmout_reset(void) { + uint16_t never_reset_mask = 0x00; + for(int i=0;ihandle.Instance) { + never_reset_tim[i] = true; + never_reset_pin_number(self->tim->pin->port, self->tim->pin->number); + break; + } + } +} + +void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) { + for(size_t i = 0 ; i < TIM_BANK_ARRAY_LEN; i++) { + if (mcu_tim_banks[i] == self->handle.Instance) { + never_reset_tim[i] = false; + break; + } + } +} + +pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, + const mcu_pin_obj_t* pin, + uint16_t duty, + uint32_t frequency, + bool variable_frequency) { + TIM_TypeDef * TIMx; + uint8_t tim_num = sizeof(mcu_tim_pin_list)/sizeof(*mcu_tim_pin_list); + bool tim_chan_taken = false; + bool tim_taken_f_mismatch = false; + bool var_freq_mismatch = false; + bool first_time_setup = true; + + for(uint i = 0; i < tim_num; i++) { + mcu_tim_pin_obj_t l_tim = mcu_tim_pin_list[i]; + uint8_t l_tim_index = l_tim.tim_index-1; + uint8_t l_tim_channel = l_tim.channel_index-1; + + //if pin is same + if (l_tim.pin == pin) { + //check if the timer has a channel active + if (reserved_tim[l_tim_index] != 0) { + //is it the same channel? (or all channels reserved by a var-freq) + if (reserved_tim[l_tim_index] & 1<<(l_tim_channel)) { + tim_chan_taken = true; + continue; //keep looking, might be another viable option + } + //If the frequencies are the same it's ok + if (tim_frequencies[l_tim_index] != frequency) { + tim_taken_f_mismatch = true; + continue; //keep looking + } + //you can't put a variable frequency on a partially reserved timer + if (variable_frequency) { + var_freq_mismatch = true; + continue; //keep looking + } + first_time_setup = false; //skip setting up the timer + } + //No problems taken, so set it up + self->tim = &l_tim; + break; + } + } + + //handle valid/invalid timer instance + if (self->tim!=NULL) { + //create instance + TIMx = mcu_tim_banks[self->tim->tim_index-1]; + //reserve timer/channel + if (variable_frequency) { + reserved_tim[self->tim->tim_index-1] = 0x0F; + } else { + reserved_tim[self->tim->tim_index-1] |= 1<<(self->tim->channel_index-1); + } + tim_frequencies[self->tim->tim_index-1] = frequency; + } else { //no match found + if (tim_chan_taken) { + mp_raise_ValueError(translate("No more timers available on this pin.")); + } else if (tim_taken_f_mismatch) { + mp_raise_ValueError(translate("Frequency must be the same as as the existing PWMOut using this timer")); + } else if (var_freq_mismatch) { + mp_raise_ValueError(translate("Cannot vary frequency on a timer that is already in use")); + } else { + mp_raise_ValueError(translate("Invalid pins")); + } + } + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = pin_mask(pin->number); + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = self->tim->altfn_index; + HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); + + tim_clock_enable(1<<(self->tim->tim_index - 1)); + + //translate channel into handle value + self->channel = 4 * (self->tim->channel_index - 1); + + uint32_t prescaler = 0; //prescaler is 15 bit + uint32_t period = 0; //period is 16 bit + timer_get_optimal_divisors(&period, &prescaler,frequency,timer_get_source_freq(self->tim->tim_index)); + + //Timer init + self->handle.Instance = TIMx; + self->handle.Init.Period = period - 1; + self->handle.Init.Prescaler = prescaler - 1; + self->handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + self->handle.Init.CounterMode = TIM_COUNTERMODE_UP; + self->handle.Init.RepetitionCounter = 0; + + //only run init if this is the first instance of this timer + if (first_time_setup) { + if (HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { + mp_raise_ValueError(translate("Could not initialize timer")); + } + } + + //Channel/PWM init + self->chan_handle.OCMode = TIM_OCMODE_PWM1; + self->chan_handle.Pulse = timer_get_internal_duty(duty, period); + self->chan_handle.OCPolarity = TIM_OCPOLARITY_LOW; + self->chan_handle.OCFastMode = TIM_OCFAST_DISABLE; + self->chan_handle.OCNPolarity = TIM_OCNPOLARITY_LOW; // needed for TIM1 and TIM8 + self->chan_handle.OCIdleState = TIM_OCIDLESTATE_SET; // needed for TIM1 and TIM8 + self->chan_handle.OCNIdleState = TIM_OCNIDLESTATE_SET; // needed for TIM1 and TIM8 + if (HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Could not initialize channel")); + } + if (HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Could not start PWM")); + } + + self->variable_frequency = variable_frequency; + self->frequency = frequency; + self->duty_cycle = duty; + self->period = period; + + return PWMOUT_OK; +} + +bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self) { + return self->tim == mp_const_none; +} + +void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { + if (common_hal_pulseio_pwmout_deinited(self)) { + return; + } + //var freq shuts down entire timer, others just their channel + if (self->variable_frequency) { + reserved_tim[self->tim->tim_index-1] = 0x00; + } else { + reserved_tim[self->tim->tim_index-1] &= ~(1<tim->channel_index); + HAL_TIM_PWM_Stop(&self->handle, self->channel); + } + reset_pin_number(self->tim->pin->port,self->tim->pin->number); + self->tim = mp_const_none; + + //if reserved timer has no active channels, we can disable it + if (!reserved_tim[self->tim->tim_index-1]) { + tim_frequencies[self->tim->tim_index-1] = 0x00; + tim_clock_disable(1<<(self->tim->tim_index-1)); + } +} + +void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) { + uint32_t internal_duty_cycle = timer_get_internal_duty(duty, self->period); + __HAL_TIM_SET_COMPARE(&self->handle, self->channel, internal_duty_cycle); + self->duty_cycle = duty; +} + +uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { + return self->duty_cycle; +} + +void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) { + //don't halt setup for the same frequency + if (frequency == self->frequency) return; + + uint32_t prescaler = 0; + uint32_t period = 0; + timer_get_optimal_divisors(&period, &prescaler,frequency,timer_get_source_freq(self->tim->tim_index)); + + //shut down + HAL_TIM_PWM_Stop(&self->handle, self->channel); + + //Only change altered values + self->handle.Init.Period = period - 1; + self->handle.Init.Prescaler = prescaler - 1; + + //restart everything, adjusting for new speed + if (HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { + mp_raise_ValueError(translate("Could not re-init timer")); + } + + self->chan_handle.Pulse = timer_get_internal_duty(self->duty_cycle, period); + + if (HAL_TIM_PWM_ConfigChannel(&self->handle, &self->chan_handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Could not re-init channel")); + } + if (HAL_TIM_PWM_Start(&self->handle, self->channel) != HAL_OK) { + mp_raise_ValueError(translate("Could not restart PWM")); + } + + tim_frequencies[self->tim->tim_index-1] = frequency; + self->frequency = frequency; + self->period = period; +} + +uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { + return self->frequency; +} + +bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) { + return self->variable_frequency; +} + +STATIC void tim_clock_enable(uint16_t mask) { + #ifdef TIM1 + if (mask & 1<<0) __HAL_RCC_TIM1_CLK_ENABLE(); + #endif + #ifdef TIM2 + if (mask & 1<<1) __HAL_RCC_TIM2_CLK_ENABLE(); + #endif + #ifdef TIM3 + if (mask & 1<<2) __HAL_RCC_TIM3_CLK_ENABLE(); + #endif + #ifdef TIM4 + if (mask & 1<<3) __HAL_RCC_TIM4_CLK_ENABLE(); + #endif + #ifdef TIM5 + if (mask & 1<<4) __HAL_RCC_TIM5_CLK_ENABLE(); + #endif + //6 and 7 are reserved ADC timers + #ifdef TIM8 + if (mask & 1<<7) __HAL_RCC_TIM8_CLK_ENABLE(); + #endif + #ifdef TIM9 + if (mask & 1<<8) __HAL_RCC_TIM9_CLK_ENABLE(); + #endif + #ifdef TIM10 + if (mask & 1<<9) __HAL_RCC_TIM10_CLK_ENABLE(); + #endif + #ifdef TIM11 + if (mask & 1<<10) __HAL_RCC_TIM11_CLK_ENABLE(); + #endif + #ifdef TIM12 + if (mask & 1<<11) __HAL_RCC_TIM12_CLK_ENABLE(); + #endif + #ifdef TIM13 + if (mask & 1<<12) __HAL_RCC_TIM13_CLK_ENABLE(); + #endif + #ifdef TIM14 + if (mask & 1<<13) __HAL_RCC_TIM14_CLK_ENABLE(); + #endif +} + +STATIC void tim_clock_disable(uint16_t mask) { + #ifdef TIM1 + if (mask & 1<<0) __HAL_RCC_TIM1_CLK_DISABLE(); + #endif + #ifdef TIM2 + if (mask & 1<<1) __HAL_RCC_TIM2_CLK_DISABLE(); + #endif + #ifdef TIM3 + if (mask & 1<<2) __HAL_RCC_TIM3_CLK_DISABLE(); + #endif + #ifdef TIM4 + if (mask & 1<<3) __HAL_RCC_TIM4_CLK_DISABLE(); + #endif + #ifdef TIM5 + if (mask & 1<<4) __HAL_RCC_TIM5_CLK_DISABLE(); + #endif + //6 and 7 are reserved ADC timers + #ifdef TIM8 + if (mask & 1<<7) __HAL_RCC_TIM8_CLK_DISABLE(); + #endif + #ifdef TIM9 + if (mask & 1<<8) __HAL_RCC_TIM9_CLK_DISABLE(); + #endif + #ifdef TIM10 + if (mask & 1<<9) __HAL_RCC_TIM10_CLK_DISABLE(); + #endif + #ifdef TIM11 + if (mask & 1<<10) __HAL_RCC_TIM11_CLK_DISABLE(); + #endif + #ifdef TIM12 + if (mask & 1<<11) __HAL_RCC_TIM12_CLK_DISABLE(); + #endif + #ifdef TIM13 + if (mask & 1<<12) __HAL_RCC_TIM13_CLK_DISABLE(); + #endif + #ifdef TIM14 + if (mask & 1<<13) __HAL_RCC_TIM14_CLK_DISABLE(); + #endif +} diff --git a/shared-bindings/_bleio/Central.h b/ports/stm32f4/common-hal/pulseio/PWMOut.h similarity index 56% rename from shared-bindings/_bleio/Central.h rename to ports/stm32f4/common-hal/pulseio/PWMOut.h index 85d788654f..59fc04e5ff 100644 --- a/shared-bindings/_bleio/Central.h +++ b/ports/stm32f4/common-hal/pulseio/PWMOut.h @@ -3,8 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2019 Lucian Copeland 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 @@ -25,19 +24,28 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H +#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H +#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H -#include "py/objtuple.h" -#include "common-hal/_bleio/Central.h" -#include "common-hal/_bleio/Service.h" +#include "common-hal/microcontroller/Pin.h" -extern const mp_obj_type_t bleio_central_type; +#include "stm32f4xx_hal.h" +#include "stm32f4/periph.h" -extern void common_hal_bleio_central_construct(bleio_central_obj_t *self); -extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout); -extern void common_hal_bleio_central_disconnect(bleio_central_obj_t *self); -extern bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self); -extern mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist); +#include "py/obj.h" -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H +typedef struct { + mp_obj_base_t base; + TIM_HandleTypeDef handle; + TIM_OC_InitTypeDef chan_handle; + const mcu_tim_pin_obj_t *tim; + uint8_t channel: 7; + bool variable_frequency: 1; + uint16_t duty_cycle; + uint32_t frequency; + uint32_t period; +} pulseio_pwmout_obj_t; + +void pwmout_reset(void); + +#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PWMOUT_H diff --git a/ports/stm32f4/common-hal/pulseio/PulseIn.c b/ports/stm32f4/common-hal/pulseio/PulseIn.c new file mode 100644 index 0000000000..068936bdd0 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PulseIn.c @@ -0,0 +1,79 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Lucian Copeland 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 "common-hal/pulseio/PulseIn.h" +#include +#include +#include "py/mpconfig.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/pulseio/PulseIn.h" +#include "tick.h" + +void pulsein_reset(void) { +} + +void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin, + uint16_t maxlen, bool idle_state) { + mp_raise_NotImplementedError(translate("PulseIn not yet supported")); +} + +bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) { + return true; +} + +void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) { +} + +void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) { +} + +void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t trigger_duration) { +} + +void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) { +} + +uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) { + return 0; +} + +uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) { + return 0; +} + +uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t* self) { + return 0; +} + +bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) { + return 0; +} + +uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) { + return 0; +} diff --git a/ports/stm32f4/common-hal/pulseio/PulseIn.h b/ports/stm32f4/common-hal/pulseio/PulseIn.h new file mode 100644 index 0000000000..2538b07ab5 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PulseIn.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Lucian Copeland 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_STM32F4_COMMON_HAL_PULSEIO_PULSEIN_H +#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEIN_H + +#include "common-hal/microcontroller/Pin.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + + uint8_t pin; + bool idle_state; + bool paused; + volatile bool first_edge; + + uint16_t* buffer; + uint16_t maxlen; + + volatile uint16_t start; + volatile uint16_t len; + volatile uint16_t last_us; + volatile uint64_t last_ms; +} pulseio_pulsein_obj_t; + +void pulsein_reset(void); + +#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEIN_H diff --git a/ports/stm32f4/common-hal/pulseio/PulseOut.c b/ports/stm32f4/common-hal/pulseio/PulseOut.c new file mode 100644 index 0000000000..d393afc5c6 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/PulseOut.c @@ -0,0 +1,55 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Lucian Copeland 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 "common-hal/pulseio/PulseOut.h" + +#include + +#include "py/mpconfig.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "shared-bindings/pulseio/PulseOut.h" +#include "shared-bindings/pulseio/PWMOut.h" +#include "supervisor/shared/translate.h" + + +void pulseout_reset() { +} + +void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, + const pulseio_pwmout_obj_t* carrier) { + mp_raise_NotImplementedError(translate("PulseOut not yet supported")); +} + +bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) { + return true; +} + +void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) { +} + +void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pulses, uint16_t length) { +} diff --git a/ports/nrf/common-hal/_bleio/Central.h b/ports/stm32f4/common-hal/pulseio/PulseOut.h similarity index 69% rename from ports/nrf/common-hal/_bleio/Central.h rename to ports/stm32f4/common-hal/pulseio/PulseOut.h index 01f7faca74..45823d28a4 100644 --- a/ports/nrf/common-hal/_bleio/Central.h +++ b/ports/stm32f4/common-hal/pulseio/PulseOut.h @@ -3,8 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2019 Lucian Copeland 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 @@ -25,20 +24,19 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H -#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H +#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEOUT_H +#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEOUT_H -#include +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/pulseio/PWMOut.h" -#include "py/objlist.h" -#include "shared-module/_bleio/Address.h" +#include "py/obj.h" typedef struct { mp_obj_base_t base; - volatile bool waiting_to_connect; - volatile uint16_t conn_handle; - // Services discovered after connecting to a remote peripheral. - mp_obj_list_t *remote_service_list; -} bleio_central_obj_t; + const pulseio_pwmout_obj_t *pwmout; +} pulseio_pulseout_obj_t; -#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H +void pulseout_reset(void); + +#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_PULSEIO_PULSEOUT_H diff --git a/ports/stm32f4/common-hal/pulseio/__init__.c b/ports/stm32f4/common-hal/pulseio/__init__.c new file mode 100644 index 0000000000..2bee925bc7 --- /dev/null +++ b/ports/stm32f4/common-hal/pulseio/__init__.c @@ -0,0 +1 @@ +// No pulseio module functions. diff --git a/ports/stm32f4/mpconfigport.mk b/ports/stm32f4/mpconfigport.mk index ffe586898e..bce68f99f4 100644 --- a/ports/stm32f4/mpconfigport.mk +++ b/ports/stm32f4/mpconfigport.mk @@ -20,6 +20,7 @@ CIRCUITPY_DIGITALIO = 1 CIRCUITPY_ANALOGIO = 1 CIRCUITPY_MICROCONTROLLER = 1 CIRCUITPY_BUSIO = 1 +CIRCUITPY_PULSEIO = 1 CIRCUITPY_OS = 1 CIRCUITPY_STORAGE = 1 CIRCUITPY_RANDOM = 1 diff --git a/ports/stm32f4/peripherals/stm32f4/periph.h b/ports/stm32f4/peripherals/stm32f4/periph.h index 82f179147b..d066b2be77 100644 --- a/ports/stm32f4/peripherals/stm32f4/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/periph.h @@ -99,6 +99,22 @@ typedef struct { .pin = spi_pin, \ } +//Timers +typedef struct { + uint8_t tim_index:4; + uint8_t altfn_index:4; + uint8_t channel_index:4; + const mcu_pin_obj_t * pin; +} mcu_tim_pin_obj_t; + +#define TIM(index, alt, channel, tim_pin) \ +{ \ + .tim_index = index, \ + .altfn_index = alt, \ + .channel_index = channel, \ + .pin = tim_pin, \ +} + //Starter Lines #ifdef STM32F411xE diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c index 7b0a54e55e..67faacdf6b 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.c @@ -85,4 +85,78 @@ const mcu_spi_nss_obj_t mcu_spi_nss_list[6] = { SPI(3, 6, &pin_PA04), SPI(3, 6, &pin_PA15), }; -//UART, Etc + +//Timers +//TIM6 and TIM7 are basic timers that are only used by DAC, and don't have pins +TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, + TIM11, TIM12, TIM13, TIM14}; + +const mcu_tim_pin_obj_t mcu_tim_pin_list[56] = { + TIM(2,1,1,&pin_PA00), + TIM(5,2,1,&pin_PA00), + TIM(2,1,2,&pin_PA01), + TIM(5,2,2,&pin_PA01), + TIM(2,1,3,&pin_PA02), + TIM(5,2,3,&pin_PA02), + TIM(2,1,4,&pin_PA03), + TIM(5,2,4,&pin_PA03), + TIM(9,3,1,&pin_PA02), + TIM(9,3,2,&pin_PA03), + TIM(3,2,1,&pin_PA06), + TIM(13,9,1,&pin_PA06), + TIM(3,2,2,&pin_PA07), + TIM(14,9,1,&pin_PA07), + TIM(1,1,1,&pin_PA08), + TIM(1,1,2,&pin_PA09), + TIM(1,1,3,&pin_PA10), + TIM(1,1,4,&pin_PA11), + TIM(2,1,1,&pin_PA15), + TIM(3,2,3,&pin_PB00), + TIM(3,2,4,&pin_PB01), + TIM(2,1,2,&pin_PB03), + TIM(3,2,1,&pin_PB04), + TIM(3,2,2,&pin_PB05), + TIM(4,2,1,&pin_PB06), + TIM(4,2,2,&pin_PB07), + TIM(4,2,3,&pin_PB08), + TIM(10,2,1,&pin_PB08), + TIM(4,2,4,&pin_PB09), + TIM(11,2,1,&pin_PB09), + TIM(2,1,3,&pin_PB10), + TIM(2,1,4,&pin_PB11), + TIM(12,9,1,&pin_PB14), + TIM(12,9,2,&pin_PB15), + TIM(3,2,1,&pin_PC06), + TIM(3,2,2,&pin_PC07), + TIM(3,2,3,&pin_PC08), + TIM(3,2,4,&pin_PC09), + TIM(8,3,1,&pin_PC06), + TIM(8,3,2,&pin_PC07), + TIM(8,3,3,&pin_PC08), + TIM(8,3,4,&pin_PC09), + TIM(4,2,1,&pin_PD12), + TIM(4,2,2,&pin_PD13), + TIM(4,2,3,&pin_PD14), + TIM(4,2,4,&pin_PD15), + TIM(9,3,1,&pin_PE05), + TIM(9,3,2,&pin_PE06), + TIM(1,1,1,&pin_PE09), + TIM(1,1,2,&pin_PE11), + TIM(1,1,3,&pin_PE13), + TIM(1,1,4,&pin_PE14), + TIM(10,3,1,&pin_PF06), + TIM(11,3,1,&pin_PF07), + TIM(13,9,1,&pin_PF08), + TIM(14,9,1,&pin_PF09), + // TIM(12,9,1,&pin_PH06), //TODO: include these when pin map is expanded + // TIM(12,9,2,&pin_PH09), + // TIM(5,2,1,&pin_PH10), + // TIM(5,2,2,&pin_PH11), + // TIM(5,2,3,&pin_PH12), + // TIM(5,2,4,&pin_PI00), + // TIM(8,3,4,&pin_PI02), + // TIM(8,3,1,&pin_PI05), + // TIM(8,3,2,&pin_PI06), + // TIM(8,3,3,&pin_PI07), +}; + diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h index cb9b33f6eb..89298cdab4 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f405xx/periph.h @@ -41,5 +41,10 @@ extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[6]; extern const mcu_spi_miso_obj_t mcu_spi_miso_list[6]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[6]; +#define TIM_BANK_ARRAY_LEN 14 +#define TIM_PIN_ARRAY_LEN 56 +TIM_TypeDef * mcu_tim_banks[TIM_BANK_ARRAY_LEN]; +const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN]; + #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F405XX_PERIPH_H \ No newline at end of file diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c index f0966f785f..1d4034bbf1 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.c @@ -120,3 +120,55 @@ const mcu_spi_nss_obj_t mcu_spi_nss_list[12] = { }; //UART, Etc + +//Timers +//TIM6 and TIM7 are basic timers that are only used by DAC, and don't have pins +TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, NULL, TIM9, TIM10, + TIM11, NULL, NULL, NULL}; + +const mcu_tim_pin_obj_t mcu_tim_pin_list[44] = { + TIM(2,1,1,&pin_PA00), + TIM(5,2,1,&pin_PA00), + TIM(2,1,2,&pin_PA01), + TIM(5,2,2,&pin_PA01), + TIM(2,1,3,&pin_PA02), + TIM(5,2,3,&pin_PA02), + TIM(2,1,4,&pin_PA03), + TIM(5,2,4,&pin_PA03), + TIM(9,3,1,&pin_PA02), + TIM(9,3,2,&pin_PA03), + TIM(3,2,1,&pin_PA06), + TIM(3,2,2,&pin_PA07), + TIM(1,1,1,&pin_PA08), + TIM(1,1,2,&pin_PA09), + TIM(1,1,3,&pin_PA10), + TIM(1,1,4,&pin_PA11), + TIM(2,1,1,&pin_PA15), + TIM(3,2,3,&pin_PB00), + TIM(3,2,4,&pin_PB01), + TIM(2,1,2,&pin_PB03), + TIM(3,2,1,&pin_PB04), + TIM(3,2,2,&pin_PB05), + TIM(4,2,1,&pin_PB06), + TIM(4,2,2,&pin_PB07), + TIM(4,2,3,&pin_PB08), + TIM(10,2,1,&pin_PB08), + TIM(4,2,4,&pin_PB09), + TIM(11,2,1,&pin_PB09), + TIM(2,1,3,&pin_PB10), + TIM(3,2,1,&pin_PC06), + TIM(3,2,2,&pin_PC07), + TIM(3,2,3,&pin_PC08), + TIM(3,2,4,&pin_PC09), + TIM(4,2,1,&pin_PD12), + TIM(4,2,2,&pin_PD13), + TIM(4,2,3,&pin_PD14), + TIM(4,2,4,&pin_PD15), + TIM(9,3,1,&pin_PE05), + TIM(9,3,2,&pin_PE06), + TIM(1,1,1,&pin_PE09), + TIM(1,1,2,&pin_PE11), + TIM(1,1,3,&pin_PE13), + TIM(1,1,4,&pin_PE14), +}; + diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h index 08efa14ca5..3045397a35 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f411xe/periph.h @@ -41,4 +41,9 @@ extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[14]; extern const mcu_spi_miso_obj_t mcu_spi_miso_list[12]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[12]; +#define TIM_BANK_ARRAY_LEN 14 +TIM_TypeDef * mcu_tim_banks[14]; +#define TIM_PIN_ARRAY_LEN 44 +const mcu_tim_pin_obj_t mcu_tim_pin_list[44]; + #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H \ No newline at end of file diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c index ea94719ecc..edce2845b8 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c +++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.c @@ -121,3 +121,71 @@ const mcu_spi_nss_obj_t mcu_spi_nss_list[12] = { }; //UART, Etc + +//Timers +//TIM6 and TIM7 are basic timers that are only used by DAC, and don't have pins +TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10, + TIM11, TIM12, TIM13, TIM14}; + +const mcu_tim_pin_obj_t mcu_tim_pin_list[60] = { + TIM(2,1,1,&pin_PA00), + TIM(5,2,1,&pin_PA00), + TIM(2,1,2,&pin_PA01), + TIM(5,2,2,&pin_PA01), + TIM(2,1,3,&pin_PA02), + TIM(5,2,3,&pin_PA02), + TIM(2,1,4,&pin_PA03), + TIM(5,2,4,&pin_PA03), + TIM(9,3,1,&pin_PA02), + TIM(9,3,2,&pin_PA03), + TIM(3,2,1,&pin_PA06), + TIM(13,9,1,&pin_PA06), + TIM(3,2,2,&pin_PA07), + TIM(14,9,1,&pin_PA07), + TIM(1,1,1,&pin_PA08), + TIM(1,1,2,&pin_PA09), + TIM(1,1,3,&pin_PA10), + TIM(1,1,4,&pin_PA11), + TIM(2,1,1,&pin_PA15), + TIM(3,2,3,&pin_PB00), + TIM(3,2,4,&pin_PB01), + TIM(2,1,2,&pin_PB03), + TIM(3,2,1,&pin_PB04), + TIM(3,2,2,&pin_PB05), + TIM(4,2,1,&pin_PB06), + TIM(4,2,2,&pin_PB07), + TIM(4,2,3,&pin_PB08), + TIM(10,2,1,&pin_PB08), + TIM(4,2,4,&pin_PB09), + TIM(11,2,1,&pin_PB09), + TIM(2,1,3,&pin_PB10), + TIM(2,1,4,&pin_PB11), + TIM(12,9,1,&pin_PB14), + TIM(12,9,2,&pin_PB15), + TIM(3,2,1,&pin_PC06), + TIM(3,2,2,&pin_PC07), + TIM(3,2,3,&pin_PC08), + TIM(3,2,4,&pin_PC09), + TIM(8,3,1,&pin_PC06), + TIM(8,3,2,&pin_PC07), + TIM(8,3,3,&pin_PC08), + TIM(8,3,4,&pin_PC09), + TIM(4,2,1,&pin_PD12), + TIM(4,2,2,&pin_PD13), + TIM(4,2,3,&pin_PD14), + TIM(4,2,4,&pin_PD15), + TIM(9,3,1,&pin_PE05), + TIM(9,3,2,&pin_PE06), + TIM(1,1,1,&pin_PE09), + TIM(1,1,2,&pin_PE11), + TIM(1,1,3,&pin_PE13), + TIM(1,1,4,&pin_PE14), + TIM(10,3,1,&pin_PF06), + TIM(11,3,1,&pin_PF07), + TIM(13,9,1,&pin_PF08), + TIM(14,9,1,&pin_PF09), + TIM(5,2,1,&pin_PF03), + TIM(5,2,2,&pin_PF04), + TIM(5,2,3,&pin_PF05), + TIM(5,2,4,&pin_PF10), +}; diff --git a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h index d12bbba93e..49ba108273 100644 --- a/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h +++ b/ports/stm32f4/peripherals/stm32f4/stm32f412zx/periph.h @@ -42,4 +42,9 @@ extern const mcu_spi_mosi_obj_t mcu_spi_mosi_list[14]; extern const mcu_spi_miso_obj_t mcu_spi_miso_list[12]; extern const mcu_spi_nss_obj_t mcu_spi_nss_list[12]; +#define TIM_BANK_ARRAY_LEN 14 +TIM_TypeDef * mcu_tim_banks[14]; +#define TIM_PIN_ARRAY_LEN 60 +const mcu_tim_pin_obj_t mcu_tim_pin_list[60]; + #endif // MICROPY_INCLUDED_STM32F4_PERIPHERALS_STM32F411VE_PERIPH_H \ No newline at end of file diff --git a/ports/stm32f4/supervisor/port.c b/ports/stm32f4/supervisor/port.c index 502202f522..602bec4be8 100644 --- a/ports/stm32f4/supervisor/port.c +++ b/ports/stm32f4/supervisor/port.c @@ -33,6 +33,7 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" +#include "common-hal/pulseio/PWMOut.h" #include "stm32f4/clocks.h" #include "stm32f4/gpio.h" @@ -57,6 +58,7 @@ void reset_port(void) { reset_all_pins(); i2c_reset(); spi_reset(); + pwmout_reset(); } void reset_to_bootloader(void) { diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index b72d753904..211e853689 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -229,12 +229,10 @@ SRC_COMMON_HAL_ALL = \ _bleio/__init__.c \ _bleio/Adapter.c \ _bleio/Attribute.c \ - _bleio/Central.c \ _bleio/Characteristic.c \ _bleio/CharacteristicBuffer.c \ + _bleio/Connection.c \ _bleio/Descriptor.c \ - _bleio/Peripheral.c \ - _bleio/Scanner.c \ _bleio/Service.c \ _bleio/UUID.c \ analogio/AnalogIn.c \ @@ -307,6 +305,7 @@ SRC_SHARED_MODULE_ALL = \ _bleio/Address.c \ _bleio/Attribute.c \ _bleio/ScanEntry.c \ + _bleio/ScanResults.c \ _pixelbuf/PixelBuf.c \ _pixelbuf/__init__.c \ _stage/Layer.c \ diff --git a/py/ringbuf.h b/py/ringbuf.h index 5f82cc0968..7fc35d2661 100644 --- a/py/ringbuf.h +++ b/py/ringbuf.h @@ -99,4 +99,11 @@ static inline void ringbuf_put_n(ringbuf_t* r, uint8_t* buf, uint8_t bufsize) } } } + +static inline void ringbuf_get_n(ringbuf_t* r, uint8_t* buf, uint8_t bufsize) +{ + for(uint8_t i=0; i < bufsize; i++) { + buf[i] = ringbuf_get(r); + } +} #endif // MICROPY_INCLUDED_PY_RINGBUF_H diff --git a/py/vm.c b/py/vm.c index b5f53ee9a0..353fc88100 100644 --- a/py/vm.c +++ b/py/vm.c @@ -758,7 +758,7 @@ unwind_jump:; } else { PUSH(value); // push the next iteration value } - DISPATCH(); + DISPATCH_WITH_PEND_EXC_CHECK(); } // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 0caca96b86..a64167e5a7 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -25,22 +25,45 @@ * THE SOFTWARE. */ +#include + #include "py/objproperty.h" +#include "py/runtime.h" #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/Adapter.h" +#define ADV_INTERVAL_MIN (0.0020f) +#define ADV_INTERVAL_MIN_STRING "0.0020" +#define ADV_INTERVAL_MAX (10.24f) +#define ADV_INTERVAL_MAX_STRING "10.24" +// 20ms is recommended by Apple +#define ADV_INTERVAL_DEFAULT (0.1f) + +#define INTERVAL_DEFAULT (0.1f) +#define INTERVAL_MIN (0.0025f) +#define INTERVAL_MIN_STRING "0.0025" +#define INTERVAL_MAX (40.959375f) +#define INTERVAL_MAX_STRING "40.959375" +#define WINDOW_DEFAULT (0.1f) + //| .. currentmodule:: _bleio //| -//| :class:`Adapter` --- BLE adapter information +//| :class:`Adapter` --- BLE adapter //| ---------------------------------------------------- //| -//| Get current status of the BLE adapter +//| The Adapter manages the discovery and connection to other nearby Bluetooth Low Energy devices. +//| This part of the Bluetooth Low Energy Specification is known as Generic Access Profile (GAP). //| -//| Usage:: +//| Discovery of other devices happens during a scanning process that listens for small packets of +//| information, known as advertisements, that are broadcast unencrypted. The advertising packets +//| have two different uses. The first is to broadcast a small piece of data to anyone who cares and +//| and nothing more. These are known as Beacons. The second class of advertisement is to promote +//| additional functionality available after the devices establish a connection. For example, a +//| BLE keyboard may advertise that it can provide key information, but not what the key info is. //| -//| import _bleio -//| _bleio.adapter.enabled = True -//| print(_bleio.adapter.address) +//| The built-in BLE adapter can do both parts of this process: it can scan for other device +//| advertisements and it can advertise its own data. Furthermore, Adapters can accept incoming +//| connections and also initiate connections. //| //| .. class:: Adapter() @@ -49,19 +72,19 @@ //| Use `_bleio.adapter` to access the sole instance available. //| -//| .. attribute:: adapter.enabled +//| .. attribute:: enabled //| -//| State of the BLE adapter. +//| State of the BLE adapter. //| STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) { - return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled()); + return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled(self)); } MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_enabled_obj, bleio_adapter_get_enabled); static mp_obj_t bleio_adapter_set_enabled(mp_obj_t self, mp_obj_t value) { const bool enabled = mp_obj_is_true(value); - common_hal_bleio_adapter_set_enabled(enabled); + common_hal_bleio_adapter_set_enabled(self, enabled); return mp_const_none; } @@ -74,12 +97,12 @@ const mp_obj_property_t bleio_adapter_enabled_obj = { (mp_obj_t)&mp_const_none_obj }, }; -//| .. attribute:: adapter.address +//| .. attribute:: address //| -//| MAC address of the BLE adapter. (read-only) +//| MAC address of the BLE adapter. (read-only) //| STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) { - return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address()); + return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address(self)); } MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address); @@ -91,29 +114,260 @@ const mp_obj_property_t bleio_adapter_address_obj = { (mp_obj_t)&mp_const_none_obj }, }; -//| .. attribute:: adapter.default_name +//| .. attribute:: name //| -//| default_name of the BLE adapter. (read-only) -//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``, -//| to make it easy to distinguish multiple CircuitPython boards. +//| name of the BLE adapter used once connected. Not used in advertisements. +//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``, +//| to make it easy to distinguish multiple CircuitPython boards. //| -STATIC mp_obj_t bleio_adapter_get_default_name(mp_obj_t self) { - return common_hal_bleio_adapter_get_default_name(); +STATIC mp_obj_t bleio_adapter_get_name(mp_obj_t self) { + return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_name(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_name_obj, bleio_adapter_get_name); + + +STATIC mp_obj_t bleio_adapter_set_name(mp_obj_t self, mp_obj_t new_name) { + common_hal_bleio_adapter_set_name(self, mp_obj_str_get_str(new_name)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(bleio_adapter_set_name_obj, bleio_adapter_set_name); + +const mp_obj_property_t bleio_adapter_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_adapter_get_name_obj, + (mp_obj_t)&bleio_adapter_set_name_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=0.1) +//| +//| Starts advertising until `stop_advertising` is called or if connectable, another device +//| connects to us. +//| +//| :param buf data: advertising data packet bytes +//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed. +//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral. +//| :param float interval: advertising interval, in seconds +//| +STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_interval }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_scan_response, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + 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 data_bufinfo; + mp_get_buffer_raise(args[ARG_data].u_obj, &data_bufinfo, MP_BUFFER_READ); + + // Pass an empty buffer if scan_response not provided. + mp_buffer_info_t scan_response_bufinfo = { 0 }; + if (args[ARG_scan_response].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_scan_response].u_obj, &scan_response_bufinfo, MP_BUFFER_READ); + } + + if (args[ARG_interval].u_obj == MP_OBJ_NULL) { + args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT); + } + + const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); + if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) { + mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), + ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING); + } + + common_hal_bleio_adapter_start_advertising(self, args[ARG_connectable].u_bool, interval, + &data_bufinfo, &scan_response_bufinfo); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_advertising_obj, 2, bleio_adapter_start_advertising); + +//| .. method:: stop_advertising() +//| +//| Stop sending advertising packets. +STATIC mp_obj_t bleio_adapter_stop_advertising(mp_obj_t self_in) { + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_adapter_stop_advertising(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapter_stop_advertising); + +//| .. method:: start_scan(prefixes=b"", \*, buffer_size=512, extended=False, timeout=None, interval=0.1, window=0.1, minimum_rssi=-80) +//| +//| Starts a BLE scan and returns an iterator of results. Advertisements and scan responses are +//| filtered and returned separately. +//| +//| :param sequence prefixes: Sequence of byte string prefixes to filter advertising packets +//| with. A packet without an advertising structure that matches one of the prefixes is +//| ignored. Format is one byte for length (n) and n bytes of prefix and can be repeated. +//| :param int buffer_size: the maximum number of advertising bytes to buffer. +//| :param bool extended: When True, support extended advertising packets. Increasing buffer_size is recommended when this is set. +//| :param float timeout: the scan timeout in seconds. If None, will scan until `stop_scan` is called. +//| :param float interval: the interval (in seconds) between the start of two consecutive scan windows +//| Must be in the range 0.0025 - 40.959375 seconds. +//| :param float window: the duration (in seconds) to scan a single BLE channel. +//| window must be <= interval. +//| :param int minimum_rssi: the minimum rssi of entries to return. +//| :param bool active: retrieve scan responses for scannable advertisements. +//| :returns: an iterable of `_bleio.ScanEntry` objects +//| :rtype: iterable +//| +STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_prefixes, ARG_buffer_size, ARG_extended, ARG_timeout, ARG_interval, ARG_window, ARG_minimum_rssi, ARG_active }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_prefixes, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 512} }, + { MP_QSTR_extended, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_minimum_rssi, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -80} }, + { MP_QSTR_active, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + }; + + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + 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_float_t timeout = 0; + if (args[ARG_timeout].u_obj != MP_OBJ_NULL) { + timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + } + + if (args[ARG_interval].u_obj == MP_OBJ_NULL) { + args[ARG_interval].u_obj = mp_obj_new_float(INTERVAL_DEFAULT); + } + + if (args[ARG_window].u_obj == MP_OBJ_NULL) { + args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT); + } + + const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); + if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { + mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING); + } + + const mp_float_t window = mp_obj_float_get(args[ARG_window].u_obj); + if (window > interval) { + mp_raise_ValueError(translate("window must be <= interval")); + } + + mp_buffer_info_t prefix_bufinfo; + prefix_bufinfo.len = 0; + if (args[ARG_prefixes].u_obj != MP_OBJ_NULL) { + mp_get_buffer_raise(args[ARG_prefixes].u_obj, &prefix_bufinfo, MP_BUFFER_READ); + if (gc_nbytes(prefix_bufinfo.buf) == 0) { + mp_raise_ValueError(translate("Prefix buffer must be on the heap")); + } + } + + return common_hal_bleio_adapter_start_scan(self, prefix_bufinfo.buf, prefix_bufinfo.len, args[ARG_extended].u_bool, args[ARG_buffer_size].u_int, timeout, interval, window, args[ARG_minimum_rssi].u_int, args[ARG_active].u_bool); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_scan_obj, 1, bleio_adapter_start_scan); + +//| .. method:: stop_scan() +//| +//| Stop the current scan. +STATIC mp_obj_t bleio_adapter_stop_scan(mp_obj_t self_in) { + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_adapter_stop_scan(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_scan_obj, bleio_adapter_stop_scan); + +//| .. attribute:: connected +//| +//| True when the adapter is connected to another device regardless of who initiated the +//| connection. (read-only) +//| +STATIC mp_obj_t bleio_adapter_get_connected(mp_obj_t self) { + return mp_obj_new_bool(common_hal_bleio_adapter_get_connected(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_default_name_obj, bleio_adapter_get_default_name); +MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_connected_obj, bleio_adapter_get_connected); -const mp_obj_property_t bleio_adapter_default_name_obj = { +const mp_obj_property_t bleio_adapter_connected_obj = { .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_adapter_get_default_name_obj, + .proxy = { (mp_obj_t)&bleio_adapter_get_connected_obj, (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: connections +//| +//| Tuple of active connections including those initiated through +//| :py:meth:`_bleio.Adapter.connect`. (read-only) +//| +STATIC mp_obj_t bleio_adapter_get_connections(mp_obj_t self) { + return common_hal_bleio_adapter_get_connections(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_connections_obj, bleio_adapter_get_connections); + +const mp_obj_property_t bleio_adapter_connections_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_adapter_get_connections_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +//| .. method:: connect(address, *, timeout, pair=False) +//| +//| Attempts a connection to the device with the given address. +//| +//| :param Address address: The address of the peripheral to connect to +//| :param float/int timeout: Try to connect for timeout seconds. +//| +STATIC mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_address, ARG_timeout, ARG_pair }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_pair, 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 - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (!MP_OBJ_IS_TYPE(args[ARG_address].u_obj, &bleio_address_type)) { + mp_raise_ValueError(translate("Expected an Address")); + } + + bleio_address_obj_t *address = MP_OBJ_TO_PTR(args[ARG_address].u_obj); + mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + + return common_hal_bleio_adapter_connect(self, address, timeout, args[ARG_pair].u_bool); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_connect_obj, 2, bleio_adapter_connect); + + STATIC const mp_rom_map_elem_t bleio_adapter_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&bleio_adapter_enabled_obj) }, { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_adapter_address_obj) }, - { MP_ROM_QSTR(MP_QSTR_default_name), MP_ROM_PTR(&bleio_adapter_default_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_adapter_name_obj) }, + + { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_adapter_start_advertising_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_adapter_stop_advertising_obj) }, + + { MP_ROM_QSTR(MP_QSTR_start_scan), MP_ROM_PTR(&bleio_adapter_start_scan_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_scan), MP_ROM_PTR(&bleio_adapter_stop_scan_obj) }, + + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_adapter_connect_obj) }, + + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_adapter_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_connections), MP_ROM_PTR(&bleio_adapter_connections_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict_table); diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h index 932fc9c958..2ff77f755b 100644 --- a/shared-bindings/_bleio/Adapter.h +++ b/shared-bindings/_bleio/Adapter.h @@ -28,13 +28,33 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H +#include + +#include "common-hal/_bleio/Adapter.h" + +#include "py/objstr.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 bleio_address_obj_t *common_hal_bleio_adapter_get_address(void); -extern mp_obj_t common_hal_bleio_adapter_get_default_name(void); +extern bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self); +extern void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled); +extern bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self); +extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self); + +extern mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self); +extern void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name); + +extern uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len); + +extern void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo); +void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self); + +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active); +void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self); + +bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self); +mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self); +mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, bool pair); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H diff --git a/shared-bindings/_bleio/Address.c b/shared-bindings/_bleio/Address.c index cdee02b5d7..c31eb604b1 100644 --- a/shared-bindings/_bleio/Address.c +++ b/shared-bindings/_bleio/Address.c @@ -114,10 +114,11 @@ const mp_obj_property_t bleio_address_address_bytes_obj = { }; //| .. attribute:: type -//| +//| //| The address type (read-only). -//| One of the integer values: `PUBLIC`, `RANDOM_STATIC`, -//| `RANDOM_PRIVATE_RESOLVABLE`, or `RANDOM_PRIVATE_NON_RESOLVABLE`. +//| +//| One of the integer values: `PUBLIC`, `RANDOM_STATIC`, `RANDOM_PRIVATE_RESOLVABLE`, +//| or `RANDOM_PRIVATE_NON_RESOLVABLE`. //| STATIC mp_obj_t bleio_address_get_type(mp_obj_t self_in) { bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -159,6 +160,28 @@ STATIC mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_o } } +//| .. method:: __hash__() +//| +//| Returns a hash for the Address data. +//| +STATIC mp_obj_t bleio_address_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + switch (op) { + // Two Addresses are equal if their address bytes and address_type are equal + case MP_UNARY_OP_HASH: { + mp_obj_t bytes = common_hal_bleio_address_get_address_bytes(MP_OBJ_TO_PTR(self_in)); + GET_STR_HASH(bytes, h); + if (h == 0) { + GET_STR_DATA_LEN(bytes, data, len); + h = qstr_compute_hash(data, len); + } + h ^= common_hal_bleio_address_get_type(MP_OBJ_TO_PTR(self_in)); + return MP_OBJ_NEW_SMALL_INT(h); + } + default: + return MP_OBJ_NULL; // op not supported + } +} + 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_buffer_info_t buf_info; @@ -205,6 +228,7 @@ const mp_obj_type_t bleio_address_type = { .name = MP_QSTR_Address, .make_new = bleio_address_make_new, .print = bleio_address_print, + .unary_op = bleio_address_unary_op, .binary_op = bleio_address_binary_op, .locals_dict = (mp_obj_dict_t*)&bleio_address_locals_dict }; diff --git a/shared-bindings/_bleio/Central.c b/shared-bindings/_bleio/Central.c deleted file mode 100644 index 084f40cd62..0000000000 --- a/shared-bindings/_bleio/Central.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * Copyright (c) 2016 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 -#include - -#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/Address.h" -#include "shared-bindings/_bleio/Characteristic.h" -#include "shared-bindings/_bleio/Central.h" -#include "shared-bindings/_bleio/Service.h" - -//| .. currentmodule:: _bleio -//| -//| :class:`Central` -- A BLE central device -//| ========================================================= -//| -//| Implement a BLE central, which runs locally. Can connect to a given address. -//| -//| Usage:: -//| -//| import _bleio -//| -//| scanner = _bleio.Scanner() -//| entries = scanner.scan(2.5) -//| -//| my_entry = None -//| for entry in entries: -//| if entry.name is not None and entry.name == 'InterestingPeripheral': -//| my_entry = entry -//| break -//| -//| if not my_entry: -//| raise Exception("'InterestingPeripheral' not found") -//| -//| central = _bleio.Central() -//| central.connect(my_entry.address, 10) # timeout after 10 seconds -//| remote_services = central.discover_remote_services() -//| - -//| .. class:: Central() -//| -//| Create a new Central object. -//| -STATIC mp_obj_t bleio_central_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_check_num(n_args, kw_args, 0, 0, false); - - bleio_central_obj_t *self = m_new_obj(bleio_central_obj_t); - self->base.type = &bleio_central_type; - - common_hal_bleio_central_construct(self); - - return MP_OBJ_FROM_PTR(self); -} - -//| .. method:: connect(address, timeout, *, service_uuids_whitelist=None) -//| Attempts a connection to the remote peripheral. -//| -//| :param Address address: The address of the peripheral to connect to -//| :param float/int timeout: Try to connect for timeout seconds. -//| -STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - enum { ARG_address, ARG_timeout, ARG_service_uuids_whitelist }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ }, - }; - - 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); - - if (!MP_OBJ_IS_TYPE(args[ARG_address].u_obj, &bleio_address_type)) { - mp_raise_ValueError(translate("Expected an Address")); - } - - bleio_address_obj_t *address = MP_OBJ_TO_PTR(args[ARG_address].u_obj); - mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); - - // common_hal_bleio_central_connect() will validate that services is an iterable or None. - common_hal_bleio_central_connect(self, address, timeout); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_connect_obj, 3, bleio_central_connect); - - -//| .. method:: disconnect() -//| -//| Disconnects from the remote peripheral. -//| -STATIC mp_obj_t bleio_central_disconnect(mp_obj_t self_in) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in); - - common_hal_bleio_central_disconnect(self); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_disconnect_obj, bleio_central_disconnect); - -//| .. method:: discover_remote_services(service_uuids_whitelist=None) -//| Do BLE discovery for all services or for the given service UUIDS, -//| to find their handles and characteristics, and return the discovered services. -//| `Peripheral.connected` must be True. -//| -//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services -//| provided by the peripheral that you want to use. -//| The peripheral may provide more services, but services not listed are ignored -//| and will not be returned. -//| -//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. -//| -//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you -//| you must have already created a :py:class:~`UUID` object for that UUID in order for the -//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered -//| for use. (This restriction may be lifted in the future.) -//| -//| :return: A tuple of services provided by the remote peripheral. -//| -STATIC mp_obj_t bleio_central_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - enum { ARG_service_uuids_whitelist }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_service_uuids_whitelist, 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); - - if (!common_hal_bleio_central_get_connected(self)) { - mp_raise_ValueError(translate("Not connected")); - } - - return MP_OBJ_FROM_PTR(common_hal_bleio_central_discover_remote_services( - MP_OBJ_FROM_PTR(self), - args[ARG_service_uuids_whitelist].u_obj)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_discover_remote_services_obj, 1, bleio_central_discover_remote_services); - -//| .. attribute:: connected -//| -//| True if connected to a remove peripheral. -//| -STATIC mp_obj_t bleio_central_get_connected(mp_obj_t self_in) { - bleio_central_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return mp_obj_new_bool(common_hal_bleio_central_get_connected(self)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_get_connected_obj, bleio_central_get_connected); - -const mp_obj_property_t bleio_central_connected_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_central_get_connected_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -STATIC const mp_rom_map_elem_t bleio_central_locals_dict_table[] = { - // Methods - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_central_discover_remote_services_obj) }, - - // Properties - { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_central_connected_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(bleio_central_locals_dict, bleio_central_locals_dict_table); - -const mp_obj_type_t bleio_central_type = { - { &mp_type_type }, - .name = MP_QSTR_Central, - .make_new = bleio_central_make_new, - .locals_dict = (mp_obj_dict_t*)&bleio_central_locals_dict -}; diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index 1981555891..d89da2a2fa 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -45,8 +45,8 @@ //| //| There is no regular constructor for a Characteristic. A new local Characteristic can be created //| and attached to a Service by calling `add_to_service()`. -//| Remote Characteristic objects are created by `Central.discover_remote_services()` -//| or `Peripheral.discover_remote_services()` as part of remote Services. +//| Remote Characteristic objects are created by `Connection.discover_remote_services()` +//| as part of remote Services. //| //| .. method:: add_to_service(service, uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=None) @@ -134,12 +134,10 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ // Range checking on max_length arg is done by the common_hal layer, because // it may vary depending on underlying BLE implementation. common_hal_bleio_characteristic_construct( - characteristic, MP_OBJ_TO_PTR(service_obj), MP_OBJ_TO_PTR(uuid_obj), + characteristic, MP_OBJ_TO_PTR(service_obj), 0, MP_OBJ_TO_PTR(uuid_obj), properties, read_perm, write_perm, max_length, fixed_length, &initial_value_bufinfo); - common_hal_bleio_service_add_characteristic(service_obj, characteristic); - return MP_OBJ_FROM_PTR(characteristic); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_add_to_service_fun_obj, 3, bleio_characteristic_add_to_service); @@ -170,7 +168,8 @@ const mp_obj_property_t bleio_characteristic_properties_obj = { //| .. attribute:: uuid //| //| The UUID of this characteristic. (read-only) -//| Will be ``None`` if the 128-bit UUID for this characteristic is not known. +//| +//| Will be ``None`` if the 128-bit UUID for this characteristic is not known. //| STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -194,7 +193,9 @@ const mp_obj_property_t bleio_characteristic_uuid_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); - return common_hal_bleio_characteristic_get_value(self); + uint8_t temp[512]; + size_t actual_len = common_hal_bleio_characteristic_get_value(self, temp, sizeof(temp)); + return mp_obj_new_bytearray(actual_len, temp); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_characteristic_get_value); @@ -224,8 +225,20 @@ const mp_obj_property_t bleio_characteristic_value_obj = { STATIC mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); // Return list as a tuple so user won't be able to change it. - mp_obj_list_t *char_list = common_hal_bleio_characteristic_get_descriptor_list(self); - return mp_obj_new_tuple(char_list->len, char_list->items); + bleio_descriptor_obj_t *descriptors = common_hal_bleio_characteristic_get_descriptor_list(self); + bleio_descriptor_obj_t *head = descriptors; + size_t len = 0; + while (head != NULL) { + len++; + head = head->next; + } + mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL)); + head = descriptors; + for (size_t i = len - 1; i >= 0; i--) { + t->items[i] = MP_OBJ_FROM_PTR(head); + head = head->next; + } + return MP_OBJ_FROM_PTR(t); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_descriptors_obj, bleio_characteristic_get_descriptors); @@ -282,7 +295,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_ch STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_add_to_service), MP_ROM_PTR(&bleio_characteristic_add_to_service_obj) }, - { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_get_properties_obj) }, + { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_properties_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_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) }, diff --git a/shared-bindings/_bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h index a816c60506..c4356fd4b9 100644 --- a/shared-bindings/_bleio/Characteristic.h +++ b/shared-bindings/_bleio/Characteristic.h @@ -36,12 +36,12 @@ extern const mp_obj_type_t bleio_characteristic_type; -extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); -extern mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); +extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len); extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self); extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self); -extern mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self); +extern bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self); extern bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self); extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor); extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate); diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c new file mode 100644 index 0000000000..1c6931b29d --- /dev/null +++ b/shared-bindings/_bleio/Connection.c @@ -0,0 +1,171 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2016 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 "shared-bindings/_bleio/Connection.h" + +#include +#include + +#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/Address.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Service.h" + +//| .. currentmodule:: _bleio +//| +//| :class:`Connection` -- A BLE connection +//| ========================================================= +//| +//| A BLE connection to another device. Used to discover and interact with services on the other +//| device. +//| +//| Usage:: +//| +//| import _bleio +//| +//| my_entry = None +//| for entry in _bleio.adapter.scan(2.5): +//| if entry.name is not None and entry.name == 'InterestingPeripheral': +//| my_entry = entry +//| break +//| +//| if not my_entry: +//| raise Exception("'InterestingPeripheral' not found") +//| +//| connection = _bleio.adapter.connect(my_entry.address, timeout=10) +//| + +STATIC void ensure_connected(bleio_connection_obj_t *self) { + if (!common_hal_bleio_connection_get_connected(self)) { + mp_raise_ValueError(translate("Connection has been disconnected and can no longer be used. Create a new connection.")); + } +} + +//| .. class:: Connection() +//| +//| Connections cannot be made directly. Instead, to initiate a connection use `Adapter.connect`. +//| Connections may also be made when another device initiates a connection. To use a Connection +//| created by a peer, read the `Adapter.connections` property. +//| +//| .. method:: disconnect() +//| +//| Disconnects from the remote peripheral. +//| +STATIC mp_obj_t bleio_connection_disconnect(mp_obj_t self_in) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); + ensure_connected(self); + + common_hal_bleio_connection_disconnect(self->connection); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_disconnect_obj, bleio_connection_disconnect); + +//| .. method:: discover_remote_services(service_uuids_whitelist=None) +//| +//| Do BLE discovery for all services or for the given service UUIDS, +//| to find their handles and characteristics, and return the discovered services. +//| `Connection.connected` must be True. +//| +//| :param iterable service_uuids_whitelist: +//| +//| an iterable of :py:class:~`UUID` objects for the services provided by the peripheral +//| that you want to use. +//| +//| The peripheral may provide more services, but services not listed are ignored +//| and will not be returned. +//| +//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be +//| slow. +//| +//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you +//| you must have already created a :py:class:~`UUID` object for that UUID in order for the +//| service or characteristic to be discovered. Creating the UUID causes the UUID to be +//| registered for use. (This restriction may be lifted in the future.) +//| +//| :return: A tuple of `_bleio.Service` objects provided by the remote peripheral. +//| +STATIC mp_obj_t bleio_connection_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_service_uuids_whitelist }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_service_uuids_whitelist, 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); + + ensure_connected(self); + + return MP_OBJ_FROM_PTR(common_hal_bleio_connection_discover_remote_services( + self, + args[ARG_service_uuids_whitelist].u_obj)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_discover_remote_services_obj, 1, bleio_connection_discover_remote_services); + +//| .. attribute:: connected +//| +//| True if connected to a remote peer. +//| +STATIC mp_obj_t bleio_connection_get_connected(mp_obj_t self_in) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(common_hal_bleio_connection_get_connected(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_connected_obj, bleio_connection_get_connected); + +const mp_obj_property_t bleio_connection_connected_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_connection_get_connected_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_connection_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_connection_discover_remote_services_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_connection_connected_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_connection_locals_dict, bleio_connection_locals_dict_table); + +const mp_obj_type_t bleio_connection_type = { + { &mp_type_type }, + .name = MP_QSTR_Connection, + .locals_dict = (mp_obj_dict_t*)&bleio_connection_locals_dict, + .unary_op = mp_generic_unary_op, +}; diff --git a/shared-bindings/_bleio/Scanner.h b/shared-bindings/_bleio/Connection.h similarity index 66% rename from shared-bindings/_bleio/Scanner.h rename to shared-bindings/_bleio/Connection.h index cbaa778662..5de6730c99 100644 --- a/shared-bindings/_bleio/Scanner.h +++ b/shared-bindings/_bleio/Connection.h @@ -25,16 +25,17 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H -#include "py/objtype.h" -#include "common-hal/_bleio/Scanner.h" +#include "py/objtuple.h" +#include "common-hal/_bleio/Connection.h" +#include "common-hal/_bleio/Service.h" -extern const mp_obj_type_t bleio_scanner_type; +extern const mp_obj_type_t bleio_connection_type; -extern void common_hal_bleio_scanner_construct(bleio_scanner_obj_t *self); -extern mp_obj_t common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_float_t timeout, mp_float_t interval, mp_float_t window); -extern void common_hal_bleio_scanner_stop(bleio_scanner_obj_t *self); +extern void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self); +extern bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self); +extern mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist); -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c index 0ab9fe8e9e..45a95903e1 100644 --- a/shared-bindings/_bleio/Descriptor.c +++ b/shared-bindings/_bleio/Descriptor.c @@ -46,9 +46,8 @@ //| //| There is no regular constructor for a Descriptor. A new local Descriptor can be created //| and attached to a Characteristic by calling `add_to_characteristic()`. -//| Remote Descriptor objects are created by `Central.discover_remote_services()` -//| or `Peripheral.discover_remote_services()` as part of remote Characteristics -//| in the remote Services that are discovered. +//| Remote Descriptor objects are created by `Connection.discover_remote_services()` +//| as part of remote Characteristics in the remote Services that are discovered. //| //| .. classmethod:: add_to_characteristic(characteristic, uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, initial_value=b'') //| @@ -180,7 +179,9 @@ const mp_obj_property_t bleio_descriptor_characteristic_obj = { STATIC mp_obj_t bleio_descriptor_get_value(mp_obj_t self_in) { bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); - return common_hal_bleio_descriptor_get_value(self); + uint8_t temp[512]; + size_t actual_len = common_hal_bleio_descriptor_get_value(self, temp, sizeof(temp)); + return mp_obj_new_bytearray(actual_len, temp); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_value_obj, bleio_descriptor_get_value); diff --git a/shared-bindings/_bleio/Descriptor.h b/shared-bindings/_bleio/Descriptor.h index 7544bdb17b..273cb1c1e3 100644 --- a/shared-bindings/_bleio/Descriptor.h +++ b/shared-bindings/_bleio/Descriptor.h @@ -38,7 +38,7 @@ extern const mp_obj_type_t bleio_descriptor_type; extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); extern bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self); extern bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self); -extern mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self); +extern size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len); extern void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H diff --git a/shared-bindings/_bleio/Peripheral.c b/shared-bindings/_bleio/Peripheral.c deleted file mode 100644 index 0bf2927442..0000000000 --- a/shared-bindings/_bleio/Peripheral.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * Copyright (c) 2016 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 -#include - -#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/Characteristic.h" -#include "shared-bindings/_bleio/Peripheral.h" -#include "shared-bindings/_bleio/Service.h" -#include "shared-bindings/_bleio/UUID.h" -#include "shared-module/_bleio/ScanEntry.h" - -#include "common-hal/_bleio/Peripheral.h" - -#define ADV_INTERVAL_MIN (0.0020f) -#define ADV_INTERVAL_MIN_STRING "0.0020" -#define ADV_INTERVAL_MAX (10.24f) -#define ADV_INTERVAL_MAX_STRING "10.24" -// 20ms is recommended by Apple -#define ADV_INTERVAL_DEFAULT (0.1f) - -//| .. currentmodule:: _bleio -//| -//| :class:`Peripheral` -- A BLE peripheral device -//| ========================================================= -//| -//| Implement a BLE peripheral which runs locally. -//| Set up using the supplied services, and then allow advertising to be started and stopped. -//| -//| Usage:: -//| -//| from _bleio import Characteristic, Peripheral, Service -//| from adafruit_ble.advertising import ServerAdvertisement -//| -//| # Create a peripheral and start it up. -//| peripheral = _bleio.Peripheral() -//| -//| # Create a Service and add it to this Peripheral. -//| service = Service.add_to_peripheral(peripheral, _bleio.UUID(0x180f)) -//| -//| # Create a Characteristic and add it to the Service. -//| characteristic = Characteristic.add_to_service(service, -//| _bleio.UUID(0x2919), properties=Characteristic.READ | Characteristic.NOTIFY) -//| -//| adv = ServerAdvertisement(peripheral) -//| peripheral.start_advertising(adv.advertising_data_bytes, scan_response=adv.scan_response_bytes) -//| -//| while not peripheral.connected: -//| # Wait for connection. -//| pass -//| -//| .. class:: Peripheral(name=None) -//| -//| Create a new Peripheral object. -//| -//| :param str name: The name used when advertising this peripheral. If name is None, -//| _bleio.adapter.default_name will be used. -//| -STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_name }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_name, 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); - - bleio_peripheral_obj_t *self = m_new_obj(bleio_peripheral_obj_t); - self->base.type = &bleio_peripheral_type; - - mp_obj_t name = args[ARG_name].u_obj; - if (name == mp_const_none) { - name = common_hal_bleio_adapter_get_default_name(); - } else if (!MP_OBJ_IS_STR(name)) { - mp_raise_ValueError(translate("name must be a string")); - } - - common_hal_bleio_peripheral_construct(self, name); - - return MP_OBJ_FROM_PTR(self); -} - -//| .. attribute:: connected (read-only) -//| -//| True if connected to a BLE Central device. -//| -STATIC mp_obj_t bleio_peripheral_get_connected(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return mp_obj_new_bool(common_hal_bleio_peripheral_get_connected(self)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_connected_obj, bleio_peripheral_get_connected); - -const mp_obj_property_t bleio_peripheral_connected_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_peripheral_get_connected_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -//| .. attribute:: services -//| -//| A tuple of :py:class:`Service` objects offered by this peripheral. (read-only) -//| -STATIC mp_obj_t bleio_peripheral_get_services(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - // Return list as a tuple so user won't be able to change it. - mp_obj_list_t *services_list = common_hal_bleio_peripheral_get_services(self); - return mp_obj_new_tuple(services_list->len, services_list->items); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_services_obj, bleio_peripheral_get_services); - -const mp_obj_property_t bleio_peripheral_services_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_peripheral_get_services_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -//| .. attribute:: name -//| -//| The peripheral's name, included when advertising. (read-only) -//| -STATIC mp_obj_t bleio_peripheral_get_name(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return common_hal_bleio_peripheral_get_name(self); -} -MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_name_obj, bleio_peripheral_get_name); - -const mp_obj_property_t bleio_peripheral_name_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_peripheral_get_name_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -//| .. method:: start_advertising(data, *, scan_response=None, connectable=True, interval=0.1) -//| -//| Starts advertising the peripheral. The peripheral's name and -//| services are included in the advertisement packets. -//| -//| :param buf data: advertising data packet bytes -//| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed. -//| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral. -//| :param float interval: advertising interval, in seconds -//| -STATIC mp_obj_t bleio_peripheral_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - enum { ARG_data, ARG_scan_response, ARG_connectable, ARG_interval }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_scan_response, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, - { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - - 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 data_bufinfo; - mp_get_buffer_raise(args[ARG_data].u_obj, &data_bufinfo, MP_BUFFER_READ); - - // Pass an empty buffer if scan_response not provided. - mp_buffer_info_t scan_response_bufinfo = { 0 }; - if (args[ARG_scan_response].u_obj != mp_const_none) { - mp_get_buffer_raise(args[ARG_scan_response].u_obj, &scan_response_bufinfo, MP_BUFFER_READ); - } - - if (args[ARG_interval].u_obj == MP_OBJ_NULL) { - args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT); - } - - const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); - if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) { - mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), - ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING); - } - - common_hal_bleio_peripheral_start_advertising(self, args[ARG_connectable].u_bool, interval, - &data_bufinfo, &scan_response_bufinfo); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_start_advertising_obj, 2, bleio_peripheral_start_advertising); - -//| .. method:: stop_advertising() -//| -//| Stop sending advertising packets. -STATIC mp_obj_t bleio_peripheral_stop_advertising(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - common_hal_bleio_peripheral_stop_advertising(self); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_stop_advertising_obj, bleio_peripheral_stop_advertising); - -//| .. method:: disconnect() -//| -//| Disconnects from the remote central. -//| Normally the central initiates a disconnection. Use this only -//| if necessary for your application. -//| -STATIC mp_obj_t bleio_peripheral_disconnect(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - common_hal_bleio_peripheral_disconnect(self); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_disconnect_obj, bleio_peripheral_disconnect); - -//| .. method:: discover_remote_services(service_uuids_whitelist=None) -//| Do BLE discovery for all services or for the given service UUIDS, -//| to find their handles and characteristics, and return the discovered services. -//| `Peripheral.connected` must be True. -//| -//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services -//| provided by the peripheral that you want to use. -//| The peripheral may provide more services, but services not listed are ignored -//| and will not be returned. -//| -//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. -//| -//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you -//| you must have already created a :py:class:~`UUID` object for that UUID in order for the -//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered -//| for use. (This restriction may be lifted in the future.) -//| -//| Thought it is unusual for a peripheral to act as a BLE client, it can do so, and -//| needs to be able to do discovery on its peer (a central). -//| Examples include a peripheral accessing a central that provides Current Time Service, -//| Apple Notification Center Service, or Battery Service. -//| -//| :return: A tuple of services provided by the remote central. -//| -STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - enum { ARG_service_uuids_whitelist }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_service_uuids_whitelist, 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); - - if (!common_hal_bleio_peripheral_get_connected(self)) { - mp_raise_ValueError(translate("Not connected")); - } - - return MP_OBJ_FROM_PTR(common_hal_bleio_peripheral_discover_remote_services( - MP_OBJ_FROM_PTR(self), - args[ARG_service_uuids_whitelist].u_obj)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_discover_remote_services_obj, 1, bleio_peripheral_discover_remote_services); - -//| .. method:: pair() -//| -//| Request pairing with connected central. -STATIC mp_obj_t bleio_peripheral_pair(mp_obj_t self_in) { - bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - common_hal_bleio_peripheral_pair(self); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_pair_obj, bleio_peripheral_pair); - -STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = { - // Methods - { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_peripheral_discover_remote_services_obj) }, - { MP_ROM_QSTR(MP_QSTR_pair), MP_ROM_PTR(&bleio_peripheral_pair_obj) }, - - // Properties - { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) }, - { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) }, - { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(bleio_peripheral_locals_dict, bleio_peripheral_locals_dict_table); - -const mp_obj_type_t bleio_peripheral_type = { - { &mp_type_type }, - .name = MP_QSTR_Peripheral, - .make_new = bleio_peripheral_make_new, - .locals_dict = (mp_obj_dict_t*)&bleio_peripheral_locals_dict -}; diff --git a/shared-bindings/_bleio/Peripheral.h b/shared-bindings/_bleio/Peripheral.h deleted file mode 100644 index bc56a93389..0000000000 --- a/shared-bindings/_bleio/Peripheral.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * 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_PERIPHERAL_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H - -#include "py/objtuple.h" -#include "common-hal/_bleio/Peripheral.h" -#include "common-hal/_bleio/Service.h" - -extern const mp_obj_type_t bleio_peripheral_type; - -extern void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_t name); -extern void common_hal_bleio_peripheral_add_service(bleio_peripheral_obj_t *self, bleio_service_obj_t *service); -extern mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self); -extern bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self); -extern mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self); -extern void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *device, bool connectable, float interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo); -extern void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *device); -extern void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *device); -extern mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist); -extern void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *device); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H diff --git a/shared-bindings/_bleio/ScanEntry.c b/shared-bindings/_bleio/ScanEntry.c index bec380d03f..d03cd6fb55 100644 --- a/shared-bindings/_bleio/ScanEntry.c +++ b/shared-bindings/_bleio/ScanEntry.c @@ -29,6 +29,7 @@ #include #include "py/objproperty.h" +#include "py/runtime.h" #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/ScanEntry.h" #include "shared-bindings/_bleio/UUID.h" @@ -36,14 +37,43 @@ //| .. currentmodule:: _bleio //| -//| :class:`ScanEntry` -- BLE scan response entry +//| :class:`ScanEntry` -- BLE scan data //| ========================================================= //| -//| Encapsulates information about a device that was received as a -//| response to a BLE scan request. This object may only be created -//| by a `_bleio.Scanner`: it has no user-visible constructor. +//| Encapsulates information about a device that was received during scanning. It can be +//| advertisement or scan response data. This object may only be created by a `_bleio.ScanResults`: +//| it has no user-visible constructor. //| +//| .. class:: ScanEntry() +//| +//| Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`. +//| +//| .. method:: matches(prefixes, *, all=True) +//| +//| Returns True if the ScanEntry matches all prefixes when ``all`` is True. This is stricter +//| than the scan filtering which accepts any advertisements that match any of the prefixes +//| where all is False. +//| +STATIC mp_obj_t bleio_scanentry_matches(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_prefixes, ARG_all }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_prefixes, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_all, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + }; + + 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; + mp_get_buffer_raise(args[ARG_prefixes].u_obj, &bufinfo, MP_BUFFER_READ); + return mp_obj_new_bool(common_hal_bleio_scanentry_matches(self, bufinfo.buf, bufinfo.len, args[ARG_all].u_bool)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_scanentry_matches_obj, 2, bleio_scanentry_matches); + //| .. attribute:: address //| //| The address of the device (read-only), of type `_bleio.Address`. @@ -95,11 +125,47 @@ const mp_obj_property_t bleio_scanentry_rssi_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: connectable +//| +//| True if the device can be connected to. (read-only) +//| +STATIC mp_obj_t scanentry_get_connectable(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(common_hal_bleio_scanentry_get_connectable(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_connectable_obj, scanentry_get_connectable); + +const mp_obj_property_t bleio_scanentry_connectable_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanentry_get_connectable_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +//| .. attribute:: scan_response +//| +//| True if the entry was a scan response. (read-only) +//| +STATIC mp_obj_t scanentry_get_scan_response(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(common_hal_bleio_scanentry_get_scan_response(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_scan_response_obj, scanentry_get_scan_response); + +const mp_obj_property_t bleio_scanentry_scan_response_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanentry_get_scan_response_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_advertisement_bytes), MP_ROM_PTR(&bleio_scanentry_advertisement_bytes_obj) }, { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bleio_scanentry_rssi_obj) }, + { MP_ROM_QSTR(MP_QSTR_connectable), MP_ROM_PTR(&bleio_scanentry_connectable_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan_response), MP_ROM_PTR(&bleio_scanentry_scan_response_obj) }, + { MP_ROM_QSTR(MP_QSTR_matches), MP_ROM_PTR(&bleio_scanentry_matches_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_dict_table); diff --git a/shared-bindings/_bleio/ScanEntry.h b/shared-bindings/_bleio/ScanEntry.h index 8af1f050a8..9aeaf20d33 100644 --- a/shared-bindings/_bleio/ScanEntry.h +++ b/shared-bindings/_bleio/ScanEntry.h @@ -37,5 +37,8 @@ extern const mp_obj_type_t bleio_scanentry_type; mp_obj_t common_hal_bleio_scanentry_get_address(bleio_scanentry_obj_t *self); mp_obj_t common_hal_bleio_scanentry_get_advertisement_bytes(bleio_scanentry_obj_t *self); mp_int_t common_hal_bleio_scanentry_get_rssi(bleio_scanentry_obj_t *self); +bool common_hal_bleio_scanentry_get_connectable(bleio_scanentry_obj_t *self); +bool common_hal_bleio_scanentry_get_scan_response(bleio_scanentry_obj_t *self); +bool common_hal_bleio_scanentry_matches(bleio_scanentry_obj_t *self, uint8_t* prefixes, size_t prefixes_len, bool all); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H diff --git a/shared-bindings/_bleio/ScanResults.c b/shared-bindings/_bleio/ScanResults.c new file mode 100644 index 0000000000..dcece3d5d4 --- /dev/null +++ b/shared-bindings/_bleio/ScanResults.c @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * 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 + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/ScanResults.h" + +//| .. currentmodule:: _bleio +//| +//| :class:`ScanResults` -- An Iterator over BLE scanning results +//| =============================================================== +//| +//| Iterates over advertising data received while scanning. This object is always created +//| by a `_bleio.Adapter`: it has no user-visible constructor. +//| +STATIC mp_obj_t scanresults_iternext(mp_obj_t self_in) { + mp_check_self(MP_OBJ_IS_TYPE(self_in, &bleio_scanresults_type)); + bleio_scanresults_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t scan_entry = common_hal_bleio_scanresults_next(self); + if (scan_entry != mp_const_none) { + return scan_entry; + } + return MP_OBJ_STOP_ITERATION; +} + +//| .. class:: ScanResults() +//| +//| Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`. +//| +//| .. method:: __iter__() +//| +//| Returns itself since it is the iterator. +//| +//| .. method:: __next__() +//| +//| Returns the next `_bleio.ScanEntry`. Blocks if none have been received and scanning is still +//| active. Raises `StopIteration` if scanning is finished and no other results are available. +//| + +const mp_obj_type_t bleio_scanresults_type = { + { &mp_type_type }, + .name = MP_QSTR_ScanResults, + .getiter = mp_identity_getiter, + .iternext = scanresults_iternext, +}; diff --git a/ports/nrf/common-hal/_bleio/Scanner.h b/shared-bindings/_bleio/ScanResults.h similarity index 76% rename from ports/nrf/common-hal/_bleio/Scanner.h rename to shared-bindings/_bleio/ScanResults.h index 3768a52cb8..a8c88c215d 100644 --- a/ports/nrf/common-hal/_bleio/Scanner.h +++ b/shared-bindings/_bleio/ScanResults.h @@ -5,6 +5,7 @@ * * Copyright (c) 2019 Dan Halbert for Adafruit Industries * 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 @@ -25,16 +26,14 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H -#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H #include "py/obj.h" +#include "shared-module/_bleio/ScanResults.h" -typedef struct { - mp_obj_base_t base; - mp_obj_t scan_entries; - uint16_t interval; - uint16_t window; -} bleio_scanner_obj_t; +extern const mp_obj_type_t bleio_scanresults_type; -#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H +mp_obj_t common_hal_bleio_scanresults_next(bleio_scanresults_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANRESULTS_H diff --git a/shared-bindings/_bleio/Scanner.c b/shared-bindings/_bleio/Scanner.c deleted file mode 100644 index 94cec97529..0000000000 --- a/shared-bindings/_bleio/Scanner.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * 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/ScanEntry.h" -#include "shared-bindings/_bleio/Scanner.h" - -#define INTERVAL_DEFAULT (0.1f) -#define INTERVAL_MIN (0.0025f) -#define INTERVAL_MIN_STRING "0.0025" -#define INTERVAL_MAX (40.959375f) -#define INTERVAL_MAX_STRING "40.959375" -#define WINDOW_DEFAULT (0.1f) - -//| .. currentmodule:: _bleio -//| -//| :class:`Scanner` -- scan for nearby BLE devices -//| ========================================================= -//| -//| Scan for nearby BLE devices. -//| -//| Usage:: -//| -//| import _bleio -//| scanner = _bleio.Scanner() -//| entries = scanner.scan(2.5) # Scan for 2.5 seconds -//| - -//| .. class:: Scanner() -//| -//| Create a new Scanner object. -//| -STATIC mp_obj_t bleio_scanner_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *all_args, mp_map_t *kw_args) { - mp_arg_check_num(n_args, kw_args, 0, 0, false); - - bleio_scanner_obj_t *self = m_new_obj(bleio_scanner_obj_t); - self->base.type = type; - - common_hal_bleio_scanner_construct(self); - - return MP_OBJ_FROM_PTR(self); -} - -//| .. method:: scan(timeout, \*, interval=0.1, window=0.1) -//| -//| Performs a BLE scan. -//| -//| :param float timeout: the scan timeout in seconds -//| :param float interval: the interval (in seconds) between the start of two consecutive scan windows -//| Must be in the range 0.0025 - 40.959375 seconds. -//| :param float window: the duration (in seconds) to scan a single BLE channel. -//| window must be <= interval. -//| :returns: an iterable of `ScanEntry` objects -//| :rtype: iterable -//| -STATIC mp_obj_t bleio_scanner_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_timeout, ARG_interval, ARG_window }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - - bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - 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); - - const mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); - - if (args[ARG_interval].u_obj == MP_OBJ_NULL) { - args[ARG_interval].u_obj = mp_obj_new_float(INTERVAL_DEFAULT); - } - - if (args[ARG_window].u_obj == MP_OBJ_NULL) { - args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT); - } - - const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); - if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { - mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING); - } - - const mp_float_t window = mp_obj_float_get(args[ARG_window].u_obj); - if (window > interval) { - mp_raise_ValueError(translate("window must be <= interval")); - } - - return common_hal_bleio_scanner_scan(self, timeout, interval, window); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_scanner_scan_obj, 2, bleio_scanner_scan); - - -STATIC const mp_rom_map_elem_t bleio_scanner_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bleio_scanner_scan_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, - .make_new = bleio_scanner_make_new, - .locals_dict = (mp_obj_dict_t*)&bleio_scanner_locals_dict -}; diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index c9b8288070..3e1ad70883 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -29,54 +29,38 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/_bleio/Characteristic.h" -#include "shared-bindings/_bleio/Peripheral.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" //| .. currentmodule:: _bleio //| -//| :class:`Service` -- BLE service +//| :class:`Service` -- BLE GATT Service //| ========================================================= //| //| Stores information about a BLE service and its characteristics. //| -//| .. class:: Service +//| .. class:: Service(uuid, *, secondary=False) //| -//| There is no regular constructor for a Service. A new local Service can be created -//| and attached to a Peripheral by calling `add_to_peripheral()`. -//| Remote Service objects are created by `Central.discover_remote_services()` -//| or `Peripheral.discover_remote_services()`. +//| Create a new Service identified by the specified UUID. It can be accessed by all +//| connections. This is known as a Service server. Client Service objects are created via +//| `Connection.discover_remote_services`. //| -//| .. classmethod:: add_to_peripheral(peripheral, uuid, *, secondary=False) +//| To mark the Service as secondary, pass `True` as :py:data:`secondary`. //| -//| Create a new Service object, identified by the specified UUID, and add it -//| to the given Peripheral. -//| -//| To mark the service as secondary, pass `True` as :py:data:`secondary`. -//| -//| :param Peripheral peripheral: The peripheral that will provide this service -//| :param UUID uuid: The uuid of the service -//| :param bool secondary: If the service is a secondary one +//| :param UUID uuid: The uuid of the service +//| :param bool secondary: If the service is a secondary one // -//| :return: the new Service +//| :return: the new Service //| -STATIC mp_obj_t bleio_service_add_to_peripheral(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - // class is arg[0], which we can ignore. - - enum { ARG_peripheral, ARG_uuid, ARG_secondary }; +STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_uuid, ARG_secondary }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_peripheral, MP_ARG_REQUIRED | MP_ARG_OBJ,}, { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, { 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 - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - const mp_obj_t peripheral_obj = args[ARG_peripheral].u_obj; - if (!MP_OBJ_IS_TYPE(peripheral_obj, &bleio_peripheral_type)) { - mp_raise_ValueError(translate("Expected a Peripheral")); - } + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); const mp_obj_t uuid_obj = args[ARG_uuid].u_obj; if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { @@ -88,19 +72,15 @@ STATIC mp_obj_t bleio_service_add_to_peripheral(size_t n_args, const mp_obj_t *p bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); service->base.type = &bleio_service_type; - common_hal_bleio_service_construct( - service, MP_OBJ_TO_PTR(peripheral_obj), MP_OBJ_TO_PTR(uuid_obj), is_secondary); - - common_hal_bleio_peripheral_add_service(peripheral_obj, service); + common_hal_bleio_service_construct(service, MP_OBJ_TO_PTR(uuid_obj), is_secondary); return MP_OBJ_FROM_PTR(service); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_service_add_to_peripheral_fun_obj, 3, bleio_service_add_to_peripheral); -STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_service_add_to_peripheral_obj, MP_ROM_PTR(&bleio_service_add_to_peripheral_fun_obj)); //| .. attribute:: characteristics //| -//| A tuple of :py:class:`Characteristic` designating the characteristics that are offered by this service. (read-only) +//| A tuple of :py:class:`Characteristic` designating the characteristics that are offered by +//| this service. (read-only) //| STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -156,7 +136,8 @@ const mp_obj_property_t bleio_service_secondary_obj = { //| .. attribute:: uuid //| //| The UUID of this service. (read-only) -//| Will be ``None`` if the 128-bit UUID for this service is not known. +//| +//| Will be ``None`` if the 128-bit UUID for this service is not known. //| STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -175,10 +156,10 @@ const mp_obj_property_t bleio_service_uuid_obj = { STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_add_to_peripheral), MP_ROM_PTR(&bleio_service_add_to_peripheral_obj) }, { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) }, { MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) }, + { MP_ROM_QSTR(MP_QSTR_remote), MP_ROM_PTR(&bleio_service_remote_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table); @@ -196,6 +177,25 @@ STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_pr const mp_obj_type_t bleio_service_type = { { &mp_type_type }, .name = MP_QSTR_Service, + .make_new = bleio_service_make_new, .print = bleio_service_print, .locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict }; + +// Helper for classes that store lists of services. +mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services) { + // Return list as a tuple so user won't be able to change it. + bleio_service_obj_t *head = services; + size_t len = 0; + while (head != NULL) { + len++; + head = head->next; + } + mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL)); + head = services; + for (int32_t i = len - 1; i >= 0; i--) { + t->items[i] = MP_OBJ_FROM_PTR(head); + head = head->next; + } + return t; +} diff --git a/shared-bindings/_bleio/Service.h b/shared-bindings/_bleio/Service.h index e061bcffcb..273c6bd989 100644 --- a/shared-bindings/_bleio/Service.h +++ b/shared-bindings/_bleio/Service.h @@ -28,16 +28,24 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H -#include "common-hal/_bleio/Peripheral.h" +#include "common-hal/_bleio/Characteristic.h" +#include "common-hal/_bleio/Connection.h" #include "common-hal/_bleio/Service.h" +#include "py/objtuple.h" + const mp_obj_type_t bleio_service_type; -extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_peripheral_obj_t *peripheral, bleio_uuid_obj_t *uuid, bool is_secondary); +// Private version that doesn't allocate on the heap +extern uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list); +extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary); +extern void common_hal_bleio_service_from_remote_service(bleio_service_obj_t *self, bleio_connection_obj_t* connection, bleio_uuid_obj_t *uuid, bool is_secondary); extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self); extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self); -extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic); +extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo); + +mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c index 3c0889aad9..dd34159022 100644 --- a/shared-bindings/_bleio/UUID.c +++ b/shared-bindings/_bleio/UUID.c @@ -156,9 +156,10 @@ STATIC mp_obj_t bleio_uuid_get_uuid128(mp_obj_t self_in) { bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); uint8_t uuid128[16]; - if (!common_hal_bleio_uuid_get_uuid128(self, uuid128)) { + if (common_hal_bleio_uuid_get_size(self) != 128) { mp_raise_AttributeError(translate("not a 128-bit UUID")); } + common_hal_bleio_uuid_get_uuid128(self, uuid128); return mp_obj_new_bytes(uuid128, 16); } @@ -192,10 +193,42 @@ const mp_obj_property_t bleio_uuid_size_obj = { (mp_obj_t)&mp_const_none_obj}, }; + +//| .. method:: pack_into(buffer, offset=0) +//| +//| Packs the UUID into the given buffer at the given offset. +//| +STATIC mp_obj_t bleio_uuid_pack_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_buffer, ARG_offset }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + + 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; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE); + + size_t offset = args[ARG_offset].u_int; + if (offset + common_hal_bleio_uuid_get_size(self) / 8 > bufinfo.len) { + mp_raise_ValueError(translate("Buffer + offset too small %d %d %d")); + } + + common_hal_bleio_uuid_pack_into(self, bufinfo.buf + offset); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_uuid_pack_into_obj, 2, bleio_uuid_pack_into); + STATIC const mp_rom_map_elem_t bleio_uuid_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_uuid16), MP_ROM_PTR(&bleio_uuid_uuid16_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid128), MP_ROM_PTR(&bleio_uuid_uuid128_obj) }, { MP_ROM_QSTR(MP_QSTR_size), MP_ROM_PTR(&bleio_uuid_size_obj) }, + { MP_ROM_QSTR(MP_QSTR_pack_into), MP_ROM_PTR(&bleio_uuid_pack_into_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_uuid_locals_dict, bleio_uuid_locals_dict_table); @@ -231,13 +264,19 @@ STATIC mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| STATIC mp_obj_t bleio_uuid_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { switch (op) { - // Two UUID's are equal if their uuid16 values and uuid128 references match. + // Two UUID's are equal if their uuid16 values match or their uuid128 values match. case MP_BINARY_OP_EQUAL: if (MP_OBJ_IS_TYPE(rhs_in, &bleio_uuid_type)) { - return mp_obj_new_bool( - common_hal_bleio_uuid_get_uuid16(lhs_in) == common_hal_bleio_uuid_get_uuid16(rhs_in) && - common_hal_bleio_uuid_get_uuid128_reference(lhs_in) == - common_hal_bleio_uuid_get_uuid128_reference(rhs_in)); + if (common_hal_bleio_uuid_get_size(lhs_in) == 16 && + common_hal_bleio_uuid_get_size(rhs_in) == 16) { + return mp_obj_new_bool(common_hal_bleio_uuid_get_uuid16(lhs_in) == + common_hal_bleio_uuid_get_uuid16(rhs_in)); + } + uint8_t lhs[16]; + uint8_t rhs[16]; + common_hal_bleio_uuid_get_uuid128(lhs_in, lhs); + common_hal_bleio_uuid_get_uuid128(rhs_in, rhs); + return mp_obj_new_bool(memcmp(lhs, rhs, sizeof(lhs)) == 0); } else { return mp_const_false; } diff --git a/shared-bindings/_bleio/UUID.h b/shared-bindings/_bleio/UUID.h index 46ac54ff39..1490737a71 100644 --- a/shared-bindings/_bleio/UUID.h +++ b/shared-bindings/_bleio/UUID.h @@ -34,10 +34,11 @@ void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t extern const mp_obj_type_t bleio_uuid_type; -extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, uint8_t uuid128[]); +extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[]); extern uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self); extern bool common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]); -extern uint32_t common_hal_bleio_uuid_get_uuid128_reference(bleio_uuid_obj_t *self); extern uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self); +void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c index f207be8cfc..0c6ebb973b 100644 --- a/shared-bindings/_bleio/__init__.c +++ b/shared-bindings/_bleio/__init__.c @@ -29,13 +29,12 @@ #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/Attribute.h" -#include "shared-bindings/_bleio/Central.h" #include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/CharacteristicBuffer.h" +#include "shared-bindings/_bleio/Connection.h" #include "shared-bindings/_bleio/Descriptor.h" -#include "shared-bindings/_bleio/Peripheral.h" #include "shared-bindings/_bleio/ScanEntry.h" -#include "shared-bindings/_bleio/Scanner.h" +#include "shared-bindings/_bleio/ScanResults.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" @@ -64,34 +63,32 @@ //| Address //| Adapter //| Attribute -//| Central //| Characteristic //| CharacteristicBuffer +//| Connection //| Descriptor -//| Peripheral //| ScanEntry -//| Scanner +//| ScanResults //| Service //| UUID //| //| .. attribute:: adapter //| -//| BLE Adapter information, such as enabled state as well as MAC -//| address. +//| BLE Adapter used to manage device discovery and connections. //| This object is the sole instance of `_bleio.Adapter`. //| 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(&bleio_adapter_type) }, { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, { MP_ROM_QSTR(MP_QSTR_Attribute), MP_ROM_PTR(&bleio_attribute_type) }, - { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) }, + { MP_ROM_QSTR(MP_QSTR_Connection), MP_ROM_PTR(&bleio_connection_type) }, { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) }, { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) }, - { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_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_ScanResults), MP_ROM_PTR(&bleio_scanresults_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) }, diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h index 67379ae2e1..92c695fa66 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -36,17 +36,19 @@ #include "common-hal/_bleio/__init__.h" #include "common-hal/_bleio/Adapter.h" -extern const super_adapter_obj_t common_hal_bleio_adapter_obj; +extern bleio_adapter_obj_t common_hal_bleio_adapter_obj; -extern void common_hal_bleio_check_connected(uint16_t conn_handle); +void common_hal_bleio_check_connected(uint16_t conn_handle); -extern uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); -extern mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device); -extern void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); +uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); +mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device); +void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); -extern mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle); -extern void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); -extern void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); +size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len); +void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); +size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len); +void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); +void common_hal_bleio_gc_collect(void); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H diff --git a/shared-module/_bleio/ScanEntry.c b/shared-module/_bleio/ScanEntry.c index 8dfa17f31f..785209c4ab 100644 --- a/shared-module/_bleio/ScanEntry.c +++ b/shared-module/_bleio/ScanEntry.c @@ -37,9 +37,50 @@ mp_obj_t common_hal_bleio_scanentry_get_address(bleio_scanentry_obj_t *self) { } mp_obj_t common_hal_bleio_scanentry_get_advertisement_bytes(bleio_scanentry_obj_t *self) { - return self->data; + return MP_OBJ_FROM_PTR(self->data); } mp_int_t common_hal_bleio_scanentry_get_rssi(bleio_scanentry_obj_t *self) { return self->rssi; } + +bool common_hal_bleio_scanentry_get_connectable(bleio_scanentry_obj_t *self) { + return self->connectable; +} + +bool common_hal_bleio_scanentry_get_scan_response(bleio_scanentry_obj_t *self) { + return self->scan_response; +} + +bool bleio_scanentry_data_matches(const uint8_t* data, size_t len, const uint8_t* prefixes, size_t prefixes_length, bool any) { + if (prefixes_length == 0) { + return true; + } + size_t i = 0; + while(i < prefixes_length) { + uint8_t prefix_length = prefixes[i]; + i += 1; + size_t j = 0; + while (j < len) { + uint8_t structure_length = data[j]; + j += 1; + if (structure_length == 0) { + break; + } + if (structure_length >= prefix_length && memcmp(data + j, prefixes + i, prefix_length) == 0) { + if (any) { + return true; + } + } else if (!any) { + return false; + } + j += structure_length; + } + i += prefix_length; + } + return !any; +} + +bool common_hal_bleio_scanentry_matches(bleio_scanentry_obj_t *self, const uint8_t* prefixes, size_t prefixes_len, bool all) { + return bleio_scanentry_data_matches(self->data->data, self->data->len, prefixes, prefixes_len, !all); +} diff --git a/shared-module/_bleio/ScanEntry.h b/shared-module/_bleio/ScanEntry.h index 1e798d78fd..94361a397d 100644 --- a/shared-module/_bleio/ScanEntry.h +++ b/shared-module/_bleio/ScanEntry.h @@ -29,14 +29,19 @@ #define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H #include "py/obj.h" +#include "py/objstr.h" #include "shared-bindings/_bleio/Address.h" typedef struct { mp_obj_base_t base; bool connectable; + bool scan_response; int8_t rssi; bleio_address_obj_t *address; - mp_obj_t data; + mp_obj_str_t *data; + uint64_t time_received; } bleio_scanentry_obj_t; +bool bleio_scanentry_data_matches(const uint8_t* data, size_t len, const uint8_t* prefixes, size_t prefix_length, bool any); + #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H diff --git a/shared-module/_bleio/ScanResults.c b/shared-module/_bleio/ScanResults.c new file mode 100644 index 0000000000..7ea0c165f4 --- /dev/null +++ b/shared-module/_bleio/ScanResults.c @@ -0,0 +1,139 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * 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 + +#include "lib/utils/interrupt_char.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/ScanEntry.h" +#include "shared-bindings/_bleio/ScanResults.h" + +bleio_scanresults_obj_t* shared_module_bleio_new_scanresults(size_t buffer_size, uint8_t* prefixes, size_t prefixes_len, mp_int_t minimum_rssi) { + bleio_scanresults_obj_t* self = m_new_obj(bleio_scanresults_obj_t); + self->base.type = &bleio_scanresults_type; + ringbuf_alloc(&self->buf, buffer_size, false); + self->prefixes = prefixes; + self->prefix_length = prefixes_len; + self->minimum_rssi = minimum_rssi; + return self; +} + +mp_obj_t common_hal_bleio_scanresults_next(bleio_scanresults_obj_t *self) { + while (ringbuf_count(&self->buf) == 0 && !self->done && !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + } + if (ringbuf_count(&self->buf) == 0 || mp_hal_is_interrupted()) { + return mp_const_none; + } + + // Create a ScanEntry out of the data on the buffer. + uint8_t type = ringbuf_get(&self->buf); + bool connectable = (type & (1 << 0)) != 0; + bool scan_response = (type & (1 << 1)) != 0; + uint64_t ticks_ms; + ringbuf_get_n(&self->buf, (uint8_t*) &ticks_ms, sizeof(ticks_ms)); + uint8_t rssi = ringbuf_get(&self->buf); + uint8_t peer_addr[NUM_BLEIO_ADDRESS_BYTES]; + ringbuf_get_n(&self->buf, peer_addr, sizeof(peer_addr)); + uint8_t addr_type = ringbuf_get(&self->buf); + uint16_t len; + ringbuf_get_n(&self->buf, (uint8_t*) &len, sizeof(len)); + + mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_bytes_of_zeros(len)); + ringbuf_get_n(&self->buf, (uint8_t*) o->data, len); + + bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t); + entry->base.type = &bleio_scanentry_type; + entry->rssi = rssi; + + bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); + address->base.type = &bleio_address_type; + common_hal_bleio_address_construct(MP_OBJ_TO_PTR(address), peer_addr, addr_type); + entry->address = address; + + entry->data = o; + entry->time_received = ticks_ms; + entry->connectable = connectable; + entry->scan_response = scan_response; + + return MP_OBJ_FROM_PTR(entry); +} + + +void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t* self, + uint64_t ticks_ms, + bool connectable, + bool scan_response, + int8_t rssi, + uint8_t *peer_addr, + uint8_t addr_type, + uint8_t *data, + uint16_t len) { + int32_t packet_size = sizeof(uint8_t) + sizeof(ticks_ms) + sizeof(rssi) + NUM_BLEIO_ADDRESS_BYTES + + sizeof(addr_type) + sizeof(len) + len; + int32_t empty_space = self->buf.size - ringbuf_count(&self->buf); + if (packet_size >= empty_space) { + // We can't fit the packet so skip it. + return; + } + // Filter the packet. + if (rssi < self->minimum_rssi) { + return; + } + + // If any prefixes are provided, then only include packets that include at least one of them. + if (!bleio_scanentry_data_matches(data, len, self->prefixes, self->prefix_length, true)) { + return; + } + uint8_t type = 0; + if (connectable) { + type |= 1 << 0; + } + if (scan_response) { + type |= 1 << 1; + } + + // Add the packet to the buffer. + ringbuf_put(&self->buf, type); + ringbuf_put_n(&self->buf, (uint8_t*) &ticks_ms, sizeof(ticks_ms)); + ringbuf_put(&self->buf, rssi); + ringbuf_put_n(&self->buf, peer_addr, NUM_BLEIO_ADDRESS_BYTES); + ringbuf_put(&self->buf, addr_type); + ringbuf_put_n(&self->buf, (uint8_t*) &len, sizeof(len)); + ringbuf_put_n(&self->buf, data, len); +} + +bool shared_module_bleio_scanresults_get_done(bleio_scanresults_obj_t* self) { + return self->done; +} + +void shared_module_bleio_scanresults_set_done(bleio_scanresults_obj_t* self, bool done) { + self->done = done; + self->common_hal_data = NULL; +} diff --git a/shared-module/_bleio/ScanResults.h b/shared-module/_bleio/ScanResults.h new file mode 100644 index 0000000000..8912357a97 --- /dev/null +++ b/shared-module/_bleio/ScanResults.h @@ -0,0 +1,64 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * 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_MODULE_BLEIO_SCANRESULTS_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H + +#include + +#include "py/obj.h" +#include "py/ringbuf.h" + +typedef struct { + mp_obj_base_t base; + // Pointers that needs to live until the scan is done. + void* common_hal_data; + ringbuf_t buf; + // Prefixes is a length encoded array of prefixes. + uint8_t* prefixes; + size_t prefix_length; + mp_int_t minimum_rssi; + bool active; + bool done; +} bleio_scanresults_obj_t; + +bleio_scanresults_obj_t* shared_module_bleio_new_scanresults(size_t buffer_size, uint8_t* prefixes, size_t prefixes_len, mp_int_t minimum_rssi); + +bool shared_module_bleio_scanresults_get_done(bleio_scanresults_obj_t* self); +void shared_module_bleio_scanresults_set_done(bleio_scanresults_obj_t* self, bool done); + +void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t* self, + uint64_t ticks_ms, + bool connectable, + bool scan_result, + int8_t rssi, + uint8_t *peer_addr, + uint8_t addr_type, + uint8_t* data, + uint16_t len); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H diff --git a/supervisor/shared/autoreload.c b/supervisor/shared/autoreload.c index 14b21902cd..a6212c1a9b 100644 --- a/supervisor/shared/autoreload.c +++ b/supervisor/shared/autoreload.c @@ -76,3 +76,11 @@ void autoreload_stop() { autoreload_delay_ms = 0; reload_requested = false; } + +void autoreload_now() { + if (!autoreload_enabled || autoreload_suspended || reload_requested) { + return; + } + mp_raise_reload_exception(); + reload_requested = true; +} diff --git a/supervisor/shared/autoreload.h b/supervisor/shared/autoreload.h index bcb1001513..fbd482c19a 100644 --- a/supervisor/shared/autoreload.h +++ b/supervisor/shared/autoreload.h @@ -43,4 +43,6 @@ bool autoreload_is_enabled(void); void autoreload_suspend(void); void autoreload_resume(void); +void autoreload_now(void); + #endif // MICROPY_INCLUDED_SUPERVISOR_AUTORELOAD_H diff --git a/supervisor/shared/bluetooth.c b/supervisor/shared/bluetooth.c new file mode 100644 index 0000000000..02258de742 --- /dev/null +++ b/supervisor/shared/bluetooth.c @@ -0,0 +1,340 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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 + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" + +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" + +#include "common-hal/_bleio/__init__.h" + +#include "supervisor/shared/autoreload.h" + +#include "py/mpstate.h" + +bleio_service_obj_t supervisor_ble_service; +bleio_uuid_obj_t supervisor_ble_service_uuid; +bleio_characteristic_obj_t supervisor_ble_version_characteristic; +bleio_uuid_obj_t supervisor_ble_version_uuid; +bleio_characteristic_obj_t supervisor_ble_filename_characteristic; +bleio_uuid_obj_t supervisor_ble_filename_uuid; +bleio_characteristic_obj_t supervisor_ble_length_characteristic; +bleio_uuid_obj_t supervisor_ble_length_uuid; +bleio_characteristic_obj_t supervisor_ble_contents_characteristic; +bleio_uuid_obj_t supervisor_ble_contents_uuid; +const uint8_t circuitpython_base_uuid[16] = {0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, 0x69, 0x75, 0x63, 0x72, 0x69, 0x43, 0x00, 0x00, 0xaf, 0xad }; +uint8_t circuitpython_advertising_data[] = { 0x02, 0x01, 0x06, 0x02, 0x0a, 0x00, 0x11, 0x07, 0x6e, 0x68, 0x74, 0x79, 0x50, 0x74, 0x69, 0x75, 0x63, 0x72, 0x69, 0x43, 0x00, 0x01, 0xaf, 0xad, 0x06, 0x08, 0x43, 0x49, 0x52, 0x43, 0x55 }; +uint8_t circuitpython_scan_response_data[15] = {0x0e, 0x09, 0x43, 0x49, 0x52, 0x43, 0x55, 0x49, 0x54, 0x50, 0x59, 0x00, 0x00, 0x00, 0x00}; +mp_obj_list_t service_list; +mp_obj_t service_list_items[1]; +mp_obj_list_t characteristic_list; +mp_obj_t characteristic_list_items[4]; + +void supervisor_bluetooth_start_advertising(void) { + bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); + if (is_connected) { + return; + } + // TODO: switch to Adafruit short UUID for the advertisement and add manufacturing data to distinguish ourselves from arduino. + _common_hal_bleio_adapter_start_advertising(&common_hal_bleio_adapter_obj, + true, + 1.0, + circuitpython_advertising_data, + sizeof(circuitpython_advertising_data), + circuitpython_scan_response_data, + sizeof(circuitpython_scan_response_data)); +} + +void supervisor_start_bluetooth(void) { + common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); + + supervisor_ble_service_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_service_uuid, 0x0100, circuitpython_base_uuid); + + // We know we'll only be 1 characteristic so we can statically allocate it. + characteristic_list.base.type = &mp_type_list; + characteristic_list.alloc = sizeof(characteristic_list_items) / sizeof(characteristic_list_items[0]); + characteristic_list.len = 0; + characteristic_list.items = characteristic_list_items; + mp_seq_clear(characteristic_list.items, 0, characteristic_list.alloc, sizeof(*characteristic_list.items)); + + _common_hal_bleio_service_construct(&supervisor_ble_service, &supervisor_ble_service_uuid, false /* is secondary */, &characteristic_list); + + // File length + supervisor_ble_version_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_version_uuid, 0x0203, circuitpython_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_version_characteristic, + &supervisor_ble_service, + 0, // handle (for remote only) + &supervisor_ble_version_uuid, + CHAR_PROP_READ, + SECURITY_MODE_OPEN, + SECURITY_MODE_NO_ACCESS, + 4, // max length + true, // fixed length + NULL); // no initial value + + uint32_t version = 1; + mp_buffer_info_t bufinfo; + bufinfo.buf = &version; + bufinfo.len = sizeof(version); + common_hal_bleio_characteristic_set_value(&supervisor_ble_version_characteristic, &bufinfo); + + // Active filename. + supervisor_ble_filename_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_filename_uuid, 0x0200, circuitpython_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_filename_characteristic, + &supervisor_ble_service, + 0, // handle (for remote only) + &supervisor_ble_filename_uuid, + CHAR_PROP_READ | CHAR_PROP_WRITE, + SECURITY_MODE_OPEN, + SECURITY_MODE_OPEN, + 500, // max length + false, // fixed length + NULL); // no initial value + + char code_py[] = "/code.py"; + bufinfo.buf = code_py; + bufinfo.len = sizeof(code_py); + common_hal_bleio_characteristic_set_value(&supervisor_ble_filename_characteristic, &bufinfo); + + // File length + supervisor_ble_length_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_length_uuid, 0x0202, circuitpython_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_length_characteristic, + &supervisor_ble_service, + 0, // handle (for remote only) + &supervisor_ble_length_uuid, + CHAR_PROP_NOTIFY | CHAR_PROP_READ, + SECURITY_MODE_OPEN, + SECURITY_MODE_NO_ACCESS, + 4, // max length + true, // fixed length + NULL); // no initial value + + // File actions + supervisor_ble_contents_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&supervisor_ble_contents_uuid, 0x0201, circuitpython_base_uuid); + common_hal_bleio_characteristic_construct(&supervisor_ble_contents_characteristic, + &supervisor_ble_service, + 0, // handle (for remote only) + &supervisor_ble_contents_uuid, + CHAR_PROP_NOTIFY | CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE, + SECURITY_MODE_OPEN, + SECURITY_MODE_OPEN, + 500, // max length + false, // fixed length + NULL); // no initial value + + supervisor_bluetooth_start_advertising(); + vm_used_ble = false; +} + +FIL active_file; +volatile bool new_filename; +volatile bool run_ble_background; +bool was_connected; + +void update_file_length(void) { + int32_t file_length = -1; + mp_buffer_info_t bufinfo; + bufinfo.buf = &file_length; + bufinfo.len = sizeof(file_length); + if (active_file.obj.fs != 0) { + file_length = (int32_t) f_size(&active_file); + } + common_hal_bleio_characteristic_set_value(&supervisor_ble_length_characteristic, &bufinfo); +} + +void open_current_file(void) { + if (active_file.obj.fs != 0) { + return; + } + uint16_t max_len = supervisor_ble_filename_characteristic.max_length; + uint8_t path[max_len]; + size_t length = common_hal_bleio_characteristic_get_value(&supervisor_ble_filename_characteristic, path, max_len - 1); + path[length] = '\0'; + + FATFS *fs = &((fs_user_mount_t *) MP_STATE_VM(vfs_mount_table)->obj)->fatfs; + f_open(fs, &active_file, (char*) path, FA_READ | FA_WRITE); + + update_file_length(); +} + +void close_current_file(void) { + f_close(&active_file); +} + +uint32_t current_command[1024 / sizeof(uint32_t)]; +volatile size_t current_offset; + +void supervisor_bluetooth_background(void) { + if (!run_ble_background) { + return; + } + bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); + if (!was_connected && is_connected) { + open_current_file(); + } else if (was_connected && !is_connected) { + close_current_file(); + new_filename = false; + } + was_connected = is_connected; + run_ble_background = false; + if (!is_connected) { + supervisor_bluetooth_start_advertising(); + return; + } + if (new_filename) { + close_current_file(); + open_current_file(); + + new_filename = false; + // get length and set the characteristic for it + } + uint16_t current_length = ((uint16_t*) current_command)[0]; + if (current_length > 0 && current_length == current_offset) { + uint16_t command = ((uint16_t *) current_command)[1]; + + if (command == 1) { + uint16_t max_len = 20; //supervisor_ble_contents_characteristic.max_length; + uint8_t buf[max_len]; + mp_buffer_info_t bufinfo; + bufinfo.buf = buf; + f_lseek(&active_file, 0); + while (f_read(&active_file, buf, max_len, &bufinfo.len) == FR_OK) { + if (bufinfo.len == 0) { + break; + } + common_hal_bleio_characteristic_set_value(&supervisor_ble_contents_characteristic, &bufinfo); + } + } else if (command == 2) { // patch + uint32_t offset = current_command[1]; + uint32_t remove_length = current_command[2]; + uint32_t insert_length = current_command[3]; + uint32_t file_length = (int32_t) f_size(&active_file); + //uint32_t data_shift_length = fileLength - offset - remove_length; + int32_t data_shift = insert_length - remove_length; + uint32_t new_length = file_length + data_shift; + + // TODO: Make these loops smarter to read and write on sector boundaries. + if (data_shift < 0) { + for (uint32_t shift_offset = offset + insert_length; shift_offset < new_length; shift_offset++) { + uint8_t data; + UINT actual; + f_lseek(&active_file, shift_offset - data_shift); + f_read(&active_file, &data, 1, &actual); + f_lseek(&active_file, shift_offset); + f_write(&active_file, &data, 1, &actual); + } + f_truncate(&active_file); + } else if (data_shift > 0) { + f_lseek(&active_file, file_length); + // Fill end with 0xff so we don't need to erase. + uint8_t data = 0xff; + for (size_t i = 0; i < (size_t) data_shift; i++) { + UINT actual; + f_write(&active_file, &data, 1, &actual); + } + for (uint32_t shift_offset = new_length - 1; shift_offset >= offset + insert_length ; shift_offset--) { + UINT actual; + f_lseek(&active_file, shift_offset - data_shift); + f_read(&active_file, &data, 1, &actual); + f_lseek(&active_file, shift_offset); + f_write(&active_file, &data, 1, &actual); + } + } + + f_lseek(&active_file, offset); + uint8_t* data = (uint8_t *) (current_command + 4); + UINT written; + f_write(&active_file, data, insert_length, &written); + f_sync(&active_file); + // Notify the new file length. + update_file_length(); + + // Trigger an autoreload + autoreload_now(); + } + current_offset = 0; + } +} + +// This happens in an interrupt so we need to be quick. +bool supervisor_bluetooth_hook(ble_evt_t *ble_evt) { + // Catch writes to filename or contents. Length is read-only. + + bool done = false; + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + // We run our background task even if it wasn't us connected to because we may want to + // advertise if the user code stopped advertising. + run_ble_background = true; + break; + case BLE_GAP_EVT_DISCONNECTED: + run_ble_background = true; + break; + case BLE_GATTS_EVT_WRITE: { + // A client wrote to a characteristic. + + ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write; + // Event handle must match the handle for my characteristic. + if (evt_write->handle == supervisor_ble_contents_characteristic.handle) { + // Handle events + //write_to_ringbuf(self, evt_write->data, evt_write->len); + // First packet includes a uint16_t le for length at the start. + uint16_t current_length = ((uint16_t*) current_command)[0]; + memcpy(((uint8_t*) current_command) + current_offset, evt_write->data, evt_write->len); + current_offset += evt_write->len; + current_length = ((uint16_t*) current_command)[0]; + if (current_offset == current_length) { + run_ble_background = true; + done = true; + } + } else if (evt_write->handle == supervisor_ble_filename_characteristic.handle) { + new_filename = true; + run_ble_background = true; + done = true; + } else { + return done; + } + break; + } + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id); + break; + } + return done; +} diff --git a/supervisor/shared/bluetooth.h b/supervisor/shared/bluetooth.h new file mode 100644 index 0000000000..7ebcb953f0 --- /dev/null +++ b/supervisor/shared/bluetooth.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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_SUPERVISOR_SHARED_BLUETOOTH_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H + +void supervisor_start_bluetooth(void); +bool supervisor_bluetooth_hook(ble_evt_t *ble_evt); +void supervisor_bluetooth_background(void); + +#endif \ No newline at end of file diff --git a/supervisor/shared/external_flash/devices.h b/supervisor/shared/external_flash/devices.h index 05091ad8cf..08d0a78fdd 100644 --- a/supervisor/shared/external_flash/devices.h +++ b/supervisor/shared/external_flash/devices.h @@ -300,6 +300,23 @@ typedef struct { .write_status_register_split = false, \ } +// Settings for the Winbond W25Q32JV-IQ 4MiB SPI flash. +// Datasheet: https://www.mouser.com/datasheet/2/949/w25q32jv_revg_03272018_plus-1489806.pdf +#define W25Q32JV_IQ {\ + .total_size = (1 << 22), /* 4 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x40, \ + .capacity = 0x16, \ + .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = true, \ + .write_status_register_split = false, \ +} + // Settings for the Winbond W25Q64JV-IM 8MiB SPI flash. Note that JV-IQ has a different .memory_type (0x40) // Datasheet: http://www.winbond.com/resource-files/w25q64jv%20revj%2003272018%20plus.pdf #define W25Q64JV_IM {\ diff --git a/supervisor/shared/safe_mode.h b/supervisor/shared/safe_mode.h index ee0723cff1..8c5dcd9c5d 100644 --- a/supervisor/shared/safe_mode.h +++ b/supervisor/shared/safe_mode.h @@ -37,7 +37,8 @@ typedef enum { MICROPY_NLR_JUMP_FAIL, MICROPY_FATAL_ERROR, GC_ALLOC_OUTSIDE_VM, - PROGRAMMATIC_SAFE_MODE + PROGRAMMATIC_SAFE_MODE, + NORDIC_SOFT_DEVICE_ASSERT } safe_mode_t; safe_mode_t wait_for_safe_mode_reset(void); diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index 48697a94ae..ad0f716fbf 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -28,6 +28,11 @@ ifneq ($(SPI_FLASH_FILESYSTEM),) CFLAGS += -DSPI_FLASH_FILESYSTEM=$(SPI_FLASH_FILESYSTEM) -DEXPRESS_BOARD endif + +ifeq ($(CIRCUITPY_BLEIO),1) + SRC_SUPERVISOR += supervisor/shared/bluetooth.c +endif + # Choose which flash filesystem impl to use. # (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive. # But that might not be true in the future.)