Merge pull request #47 from adafruit/main

Update from adafruit main
This commit is contained in:
DavePutz 2021-04-28 10:16:01 -05:00 committed by GitHub
commit 34014495d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
732 changed files with 16780 additions and 22514 deletions

View File

@ -178,8 +178,13 @@ jobs:
- "TG-Watch"
- "adafruit_feather_rp2040"
- "adafruit_itsybitsy_rp2040"
- "adafruit_neokey_trinkey_m0"
- "adafruit_proxlight_trinkey_m0"
- "adafruit_qtpy_rp2040"
- "adafruit_rotary_trinkey_m0"
- "adafruit_slide_trinkey_m0"
- "aloriumtech_evo_m51"
- "aramcon2_badge"
- "aramcon_badge_2019"
- "arduino_mkr1300"
- "arduino_mkrzero"
@ -285,6 +290,8 @@ jobs:
- "pewpew_m4"
- "picoplanet"
- "pimoroni_keybow2040"
- "pimoroni_picolipo_16mb"
- "pimoroni_picolipo_4mb"
- "pimoroni_picosystem"
- "pimoroni_tiny2040"
- "pirkey_m0"
@ -305,7 +312,6 @@ jobs:
- "raspberry_pi_pico"
- "raytac_mdbt50q-db-40"
- "robohatmm1_m4"
- "rotary_trinkey_m0"
- "sam32"
- "same54_xplained"
- "seeeduino_wio_terminal"
@ -317,6 +323,7 @@ jobs:
- "simmel"
- "snekboard"
- "sparkfun_lumidrive"
- "sparkfun_micromod_rp2040"
- "sparkfun_nrf52840_micromod"
- "sparkfun_nrf52840_mini"
- "sparkfun_pro_micro_rp2040"
@ -376,6 +383,8 @@ jobs:
python3 --version
- name: mpy-cross
run: make -C mpy-cross -j2
- name: Setup build failure matcher
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/workflows/match-build-fail.json"
- name: build
run: python3 -u build_release_files.py
working-directory: tools
@ -425,6 +434,8 @@ jobs:
python3 --version
- name: mpy-cross
run: make -C mpy-cross -j2
- name: Setup build failure matcher
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/workflows/match-build-fail.json"
- name: build
run: python3 -u build_release_files.py
working-directory: tools
@ -454,6 +465,7 @@ jobs:
- "adafruit_magtag_2.9_grayscale"
- "adafruit_metro_esp32s2"
- "artisense_rd00"
- "atmegazero_esp32s2"
- "electroniccats_bastwifi"
- "espressif_kaluga_1"
- "espressif_saola_1_wroom"
@ -486,7 +498,7 @@ jobs:
id: idf-cache
with:
path: ${{ github.workspace }}/.idf_tools
key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/esp32s2/esp-idf/HEAD') }}-20210304
key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/esp32s2/esp-idf/HEAD') }}-20210422
- name: Clone IDF submodules
run: |
(cd $IDF_PATH && git submodule update --init)
@ -523,6 +535,8 @@ jobs:
IDF_TOOLS_PATH: ${{ github.workspace }}/.idf_tools
- name: mpy-cross
run: make -C mpy-cross -j2
- name: Setup build failure matcher
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/workflows/match-build-fail.json"
- name: build
run: |
source $IDF_PATH/export.sh

14
.github/workflows/match-build-fail.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
"problemMatcher": [
{
"severity": "error",
"pattern": [
{
"regexp": "^(Build .+ and \\x1b\\[31mfailed\\x1b\\[0m)$",
"message": 1
}
],
"owner": "build-failed"
}
]
}

8
.gitmodules vendored
View File

@ -113,7 +113,7 @@
url = https://github.com/adafruit/Adafruit_CircuitPython_Register.git
[submodule "extmod/ulab"]
path = extmod/ulab
url = https://github.com/v923z/micropython-ulab
url = https://github.com/adafruit/circuitpython-ulab
[submodule "frozen/Adafruit_CircuitPython_ESP32SPI"]
path = frozen/Adafruit_CircuitPython_ESP32SPI
url = https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI
@ -171,6 +171,9 @@
[submodule "frozen/Adafruit_CircuitPython_LC709203F"]
path = frozen/Adafruit_CircuitPython_LC709203F
url = https://github.com/adafruit/Adafruit_CircuitPython_LC709203F
[submodule "frozen/Adafruit_CircuitPython_SimpleMath"]
path = frozen/Adafruit_CircuitPython_SimpleMath
url = https://github.com/adafruit/Adafruit_CircuitPython_SimpleMath
[submodule "ports/raspberrypi/sdk"]
path = ports/raspberrypi/sdk
url = https://github.com/adafruit/pico-sdk.git
@ -178,3 +181,6 @@
path = data/nvm.toml
url = https://github.com/adafruit/nvm.toml.git
branch = main
[submodule "frozen/Adafruit_CircuitPython_MIDI"]
path = frozen/Adafruit_CircuitPython_MIDI
url = https://github.com/adafruit/Adafruit_CircuitPython_MIDI

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013, 2014 Damien P. George
Copyright (c) 2013-2019 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

View File

@ -489,6 +489,8 @@ class CoreModuleTransform(SphinxTransform):
def setup(app):
app.add_css_file("customstyle.css")
app.add_css_file("filter.css")
app.add_js_file("filter.js")
app.add_config_value('redirects_file', 'redirects', 'env')
app.connect('builder-inited', generate_redirects)
app.add_transform(CoreModuleTransform)

View File

@ -886,10 +886,10 @@ uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *att
uint16_t handle = (uint16_t)adapter->attributes->len;
mp_obj_list_append(adapter->attributes, attribute);
if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) {
if (mp_obj_is_type(attribute, &bleio_service_type)) {
adapter->last_added_service_handle = handle;
}
if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
if (mp_obj_is_type(attribute, &bleio_characteristic_type)) {
adapter->last_added_characteristic_handle = handle;
}

View File

@ -33,15 +33,15 @@
bleio_uuid_obj_t *bleio_attribute_get_uuid(mp_obj_t *attribute) {
if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
if (mp_obj_is_type(attribute, &bleio_characteristic_type)) {
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute);
return characteristic->uuid;
}
if (MP_OBJ_IS_TYPE(attribute, &bleio_descriptor_type)) {
if (mp_obj_is_type(attribute, &bleio_descriptor_type)) {
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute);
return descriptor->uuid;
}
if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) {
if (mp_obj_is_type(attribute, &bleio_service_type)) {
bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute);
return service->uuid;
}

View File

@ -78,6 +78,10 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character
return self->service;
}
size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristic_obj_t *self) {
return self->max_length;
}
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) {
@ -209,9 +213,9 @@ bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_b
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
if (MP_OBJ_IS_TYPE(self->observer, &bleio_characteristic_buffer_type)) {
if (mp_obj_is_type(self->observer, &bleio_characteristic_buffer_type)) {
bleio_characteristic_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
} else if (MP_OBJ_IS_TYPE(self->observer, &bleio_packet_buffer_type)) {
} else if (mp_obj_is_type(self->observer, &bleio_packet_buffer_type)) {
bleio_packet_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
} else {
return false;

View File

@ -644,7 +644,7 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
// 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)) {
// if (!mp_obj_is_type(uuid_obj, &bleio_uuid_type)) {
// mp_raise_TypeError(translate("non-UUID found in service_uuids_whitelist"));
// }
// bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);

View File

@ -81,7 +81,7 @@ void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_
void common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
size_t buffer_size) {
size_t buffer_size, size_t max_packet_size) {
self->characteristic = characteristic;
self->client = self->characteristic->service->is_remote;
@ -101,7 +101,7 @@ void common_hal_bleio_packet_buffer_construct(
}
if (incoming) {
if (!ringbuf_alloc(&self->ringbuf, buffer_size * (sizeof(uint16_t) + characteristic->max_length), false)) {
if (!ringbuf_alloc(&self->ringbuf, buffer_size * (sizeof(uint16_t) + max_packet_size), false)) {
mp_raise_ValueError(translate("Buffer too large and unable to allocate"));
}
}
@ -110,12 +110,13 @@ void common_hal_bleio_packet_buffer_construct(
self->packet_queued = false;
self->pending_index = 0;
self->pending_size = 0;
self->outgoing[0] = m_malloc(characteristic->max_length, false);
self->outgoing[1] = m_malloc(characteristic->max_length, false);
self->outgoing[0] = m_malloc(max_packet_size, false);
self->outgoing[1] = m_malloc(max_packet_size, false);
} else {
self->outgoing[0] = NULL;
self->outgoing[1] = NULL;
}
self->max_packet_size = max_packet_size;
bleio_characteristic_set_observer(self->characteristic, self);
}
@ -243,15 +244,16 @@ mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_
if (self->conn_handle != BLE_CONN_HANDLE_INVALID) {
bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle);
if (connection) {
return MIN(common_hal_bleio_connection_get_max_packet_length(connection),
self->characteristic->max_length);
return MIN(MIN(common_hal_bleio_connection_get_max_packet_length(connection),
self->max_packet_size),
self->characteristic->max_length);
}
}
// There's no current connection, so we don't know the MTU, and
// we can't tell what the largest outgoing packet length would be.
return -1;
}
return self->characteristic->max_length;
return MIN(self->characteristic->max_length, self->max_packet_size);
}
bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {

View File

@ -42,6 +42,7 @@ typedef struct {
// We remember the conn_handle so we can do a NOTIFY/INDICATE to a client.
// We can find out the conn_handle on a Characteristic write or a CCCD write (but not a read).
volatile uint16_t conn_handle;
uint16_t max_packet_size;
uint8_t pending_index;
uint8_t write_type;
bool client;

View File

@ -539,7 +539,7 @@ void att_remove_connection(uint16_t conn_handle, uint8_t reason) {
.len = sizeof(zero),
};
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
if (mp_obj_is_type(attribute_obj, &bleio_descriptor_type)) {
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) == BLE_UUID_CCCD) {
common_hal_bleio_descriptor_set_value(descriptor, &zero_cccd_value);
@ -800,7 +800,7 @@ STATIC void process_find_info_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
// Fetch the uuid for the given attribute, which might be a characteristic or a descriptor.
bleio_uuid_obj_t *uuid;
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
if (mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
if (characteristic->handle != handle) {
// If the handles don't match, this is the characteristic definition attribute.
@ -971,7 +971,7 @@ void process_read_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, ui
}
mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_service_type)) {
if (mp_obj_is_type(attribute_obj, &bleio_service_type)) {
bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute_obj);
// Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute
@ -1083,7 +1083,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
size_t rsp_length = sizeof(rsp_t);
mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_service_type)) {
if (mp_obj_is_type(attribute_obj, &bleio_service_type)) {
if (offset) {
send_error(conn_handle, BT_ATT_ERR_ATTRIBUTE_NOT_LONG, handle, BT_ATT_ERR_INVALID_PDU);
return;
@ -1095,7 +1095,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
common_hal_bleio_uuid_pack_into(service->uuid, rsp->r.value);
rsp_length += sizeof_service_uuid;
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
} else if (mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
if (characteristic->decl_handle == handle) {
// Read characteristic declaration. Return properties, value handle, and uuid.
@ -1135,7 +1135,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui
memcpy(rsp->r.value, bufinfo.buf + offset, value_length);
rsp_length += value_length;
}
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
} else if (mp_obj_is_type(attribute_obj, &bleio_descriptor_type)) {
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
mp_buffer_info_t bufinfo;
@ -1203,7 +1203,7 @@ STATIC void process_read_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
if (type_uuid == BLE_UUID_CHARACTERISTIC &&
MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
// Request is for characteristic declarations.
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
@ -1250,7 +1250,7 @@ STATIC void process_read_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
rsp_length += data_length;
no_data = false;
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
} else if (mp_obj_is_type(attribute_obj, &bleio_descriptor_type)) {
// See if request is for a descriptor value with a 16-bit UUID, such as the CCCD.
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) == type_uuid) {
@ -1271,7 +1271,7 @@ STATIC void process_read_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl
break;
}
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
} else if (mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
// See if request is for a characteristic value with a 16-bit UUID.
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
if (bleio_uuid_get_uuid16_or_unknown(characteristic->uuid) == type_uuid) {
@ -1359,7 +1359,7 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t
mp_obj_t attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, req->handle);
if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) {
if (mp_obj_is_type(attribute_obj, &bleio_characteristic_type)) {
bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj);
// Don't write the characteristic declaration.
@ -1377,7 +1377,7 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t
// Just change the local value. Don't fire off notifications, etc.
bleio_characteristic_set_local_value(characteristic, &bufinfo);
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
} else if (mp_obj_is_type(attribute_obj, &bleio_descriptor_type)) {
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
// Only CCCD's are writable.
if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) != BLE_UUID_CCCD) {
@ -1427,7 +1427,7 @@ STATIC void process_prepare_write_req(uint16_t conn_handle, uint16_t mtu, uint8_
mp_obj_t *attribute = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
if (!MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) {
if (!mp_obj_is_type(attribute, &bleio_characteristic_type)) {
send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTRIBUTE_NOT_LONG);
return;
}

View File

@ -18,7 +18,7 @@ Start libraries with the cookiecutter
Cookiecutter is a tool that lets you bootstrap a new repo based on another repo.
We've made one `here <https://github.com/adafruit/cookiecutter-adafruit-circuitpython>`_
for CircuitPython libraries that include configs for Travis CI and ReadTheDocs
along with a setup.py, license, code of conduct and readme.
along with a setup.py, license, code of conduct, readme among other files.
.. code-block::sh
@ -252,7 +252,7 @@ At the class level document what class does and how to initialize it::
"""DS3231 real-time clock.
:param ~busio.I2C i2c_bus: The I2C bus the DS3231 is connected to.
:param int address: The I2C address of the device.
:param int address: The I2C address of the device. Defaults to :const:`0x40`
"""
def __init__(self, i2c_bus, address=0x40):
@ -267,7 +267,7 @@ Renders as:
DS3231 real-time clock.
:param ~busio.I2C i2c_bus: The I2C bus the DS3231 is connected to.
:param int address: The I2C address of the device.
:param int address: The I2C address of the device. Defaults to :const:`0x40`
Attributes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -516,6 +516,15 @@ when using ``const()``, keep in mind these general guide lines:
- If user will not need access to variable, prefix name with a leading
underscore, ex: ``_SOME_CONST``.
Libraries Examples
------------------
When adding examples, cookiecutter will add a ``<name>_simpletest.py`` file in the examples directory for you.
Be sure to include code with the library minimal functionalities to work on a device.
You could other examples if needed featuring different
functionalities of the library.
If you add additional examples, be sure to include them in the ``examples.rst``. Naming of the examples
files should use the name of the library followed by a description, using underscore to separate them.
Sensor properties and units
--------------------------------------------------------------------------------
@ -536,7 +545,7 @@ properties.
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``gyro`` | (float, float, float) | x, y, z radians per second |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``temperature`` | float | degrees centigrade |
| ``temperature`` | float | degrees Celsius |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``CO2`` | float | measured CO2 in ppm |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
@ -544,9 +553,9 @@ properties.
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``TVOC`` | float | Total Volatile Organic Compounds in ppb |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``distance`` | float | centimeters |
| ``distance`` | float | centimeters (cm) |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``proximity`` | int | non-unit-specifc proximity values (monotonic but not actual distance) |
| ``proximity`` | int | non-unit-specific proximity values (monotonic but not actual distance) |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``light`` | float | non-unit-specific light levels (should be monotonic but is not lux) |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
@ -568,7 +577,7 @@ properties.
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``duty_cycle`` | int | 16-bit PWM duty cycle (regardless of output resolution) |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``frequency`` | int | Hertz |
| ``frequency`` | int | Hertz (Hz) |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
| ``value`` | bool | Digital logic |
+-----------------------+-----------------------+-------------------------------------------------------------------------+
@ -592,9 +601,8 @@ mimic the structure in ``shared-bindings``.
To test your native modules or core enhancements, follow these Adafruit Learning Guides
for building local firmware to flash onto your device(s):
`SAMD21 - Build Firmware Learning Guide <https://learn.adafruit.com/micropython-for-samd21/build-firmware>`_
`Build CircuitPython <https://learn.adafruit.com/building-circuitpython>`_
`ESP8266 - Build Firmware Learning Guide <https://learn.adafruit.com/building-and-running-micropython-on-the-esp8266/overview>`_
MicroPython compatibility
--------------------------------------------------------------------------------

View File

@ -14,6 +14,33 @@ hold/accumulate various objects.
Classes
-------
.. function:: deque(iterable, maxlen[, flags])
Deques (double-ended queues) are a list-like container that support O(1)
appends and pops from either side of the deque. New deques are created
using the following arguments:
- *iterable* must be the empty tuple, and the new deque is created empty.
- *maxlen* must be specified and the deque will be bounded to this
maximum length. Once the deque is full, any new items added will
discard items from the opposite end.
- The optional *flags* can be 1 to check for overflow when adding items.
As well as supporting `bool` and `len`, deque objects have the following
methods:
.. method:: deque.append(x)
Add *x* to the right side of the deque.
Raises IndexError if overflow checking is enabled and there is no more room left.
.. method:: deque.popleft()
Remove and return an item from the left side of the deque.
Raises IndexError if no items are present.
.. function:: namedtuple(name, fields)
This is factory function to create a new namedtuple type with a specific

View File

@ -39,8 +39,6 @@ with the ``u`` prefix dropped:
sys.rst
uctypes.rst
uselect.rst
usocket.rst
ussl.rst
uzlib.rst
Omitted functions in the ``string`` library

View File

@ -81,6 +81,9 @@ Functions
in a row and the lock-depth will increase, and then `heap_unlock()` must be
called the same number of times to make the heap available again.
If the REPL becomes active with the heap locked then it will be forcefully
unlocked.
.. function:: kbd_intr(chr)
Set the character that will raise a `KeyboardInterrupt` exception. By

View File

@ -10,41 +10,101 @@ This module implements regular expression operations. Regular expression
syntax supported is a subset of CPython ``re`` module (and actually is
a subset of POSIX extended regular expressions).
Supported operators are:
Supported operators and special sequences are:
``'.'``
``.``
Match any character.
``'[...]'``
``[...]``
Match set of characters. Individual characters and ranges are supported,
including negated sets (e.g. ``[^a-c]``).
``'^'``
``^``
Match the start of the string.
``'$'``
``$``
Match the end of the string.
``'?'``
``?``
Match zero or one of the previous sub-pattern.
``'*'``
``*``
Match zero or more of the previous sub-pattern.
``'+'``
``+``
Match one or more of the previous sub-pattern.
``'??'``
``??``
Non-greedy version of ``?``, match zero or one, with the preference
for zero.
``'*?'``
``*?``
Non-greedy version of ``*``, match zero or more, with the preference
for the shortest match.
``'+?'``
``+?``
Non-greedy version of ``+``, match one or more, with the preference
for the shortest match.
``'|'``
``|``
Match either the left-hand side or the right-hand side sub-patterns of
this operator.
``'(...)'``
``(...)``
Grouping. Each group is capturing (a substring it captures can be accessed
with `match.group()` method).
**NOT SUPPORTED**: Counted repetitions (``{m,n}``), more advanced assertions
(``\b``, ``\B``), named groups (``(?P<name>...)``), non-capturing groups
(``(?:...)``), etc.
``\d``
Matches digit. Equivalent to ``[0-9]``.
``\D``
Matches non-digit. Equivalent to ``[^0-9]``.
``\s``
Matches whitespace. Equivalent to ``[ \t-\r]``.
``\S``
Matches non-whitespace. Equivalent to ``[^ \t-\r]``.
``\w``
Matches "word characters" (ASCII only). Equivalent to ``[A-Za-z0-9_]``.
``\W``
Matches non "word characters" (ASCII only). Equivalent to ``[^A-Za-z0-9_]``.
``\``
Escape character. Any other character following the backslash, except
for those listed above, is taken literally. For example, ``\*`` is
equivalent to literal ``*`` (not treated as the ``*`` operator).
Note that ``\r``, ``\n``, etc. are not handled specially, and will be
equivalent to literal letters ``r``, ``n``, etc. Due to this, it's
not recommended to use raw Python strings (``r""``) for regular
expressions. For example, ``r"\r\n"`` when used as the regular
expression is equivalent to ``"rn"``. To match CR character followed
by LF, use ``"\r\n"``.
**NOT SUPPORTED**:
* counted repetitions (``{m,n}``)
* named groups (``(?P<name>...)``)
* non-capturing groups (``(?:...)``)
* more advanced assertions (``\b``, ``\B``)
* special character escapes like ``\r``, ``\n`` - use Python's own escaping
instead
* etc.
Example::
import ure
# As ure doesn't support escapes itself, use of r"" strings is not
# recommended.
regex = ure.compile("[\r\n]")
regex.split("line1\rline2\nline3\r\n")
# Result:
# ['line1', 'line2', 'line3', '', '']
Functions
---------
@ -64,6 +124,22 @@ Functions
string for first position which matches regex (which still may be
0 if regex is anchored).
.. function:: sub(regex_str, replace, string, count=0, flags=0)
Compile *regex_str* and search for it in *string*, replacing all matches
with *replace*, and returning the new string.
*replace* can be a string or a function. If it is a string then escape
sequences of the form ``\<number>`` and ``\g<number>`` can be used to
expand to the corresponding group (or an empty string for unmatched groups).
If *replace* is a function then it must take a single argument (the match)
and should return a replacement string.
If *count* is specified and non-zero then substitution will stop after
this many substitutions are made. The *flags* argument is ignored.
Note: availability of this function depends on MicroPython port.
.. data:: DEBUG
Flag value, display debug information about compiled expression.
@ -79,8 +155,10 @@ Compiled regular expression. Instances of this class are created using
.. method:: regex.match(string)
regex.search(string)
regex.sub(replace, string, count=0, flags=0)
Similar to the module-level functions :meth:`match` and :meth:`search`.
Similar to the module-level functions :meth:`match`, :meth:`search`
and :meth:`sub`.
Using methods is (much) more efficient if the same regex is applied to
multiple strings.
@ -93,9 +171,31 @@ Compiled regular expression. Instances of this class are created using
Match objects
-------------
Match objects as returned by `match()` and `search()` methods.
Match objects as returned by `match()` and `search()` methods, and passed
to the replacement function in `sub()`.
.. method:: match.group([index])
.. method:: match.group(index)
Return matching (sub)string. *index* is 0 for entire match,
1 and above for each capturing group. Only numeric groups are supported.
.. method:: match.groups()
Return a tuple containing all the substrings of the groups of the match.
Note: availability of this method depends on MicroPython port.
.. method:: match.start([index])
match.end([index])
Return the index in the original string of the start or end of the
substring group that was matched. *index* defaults to the entire
group, otherwise it will select a group.
Note: availability of these methods depends on MicroPython port.
.. method:: match.span([index])
Returns the 2-tuple ``(match.start(index), match.end(index))``.
Note: availability of this method depends on MicroPython port.

View File

@ -13,19 +13,91 @@ module is to define data structure layout with about the same power as the
C language allows, and then access it using familiar dot-syntax to reference
sub-fields.
.. warning::
``uctypes`` module allows access to arbitrary memory addresses of the
machine (including I/O and control registers). Uncareful usage of it
may lead to crashes, data loss, and even hardware malfunction.
.. seealso::
Module :mod:`struct`
Standard Python way to access binary data structures (doesn't scale
well to large and complex structures).
Usage examples::
import uctypes
# Example 1: Subset of ELF file header
# https://wikipedia.org/wiki/Executable_and_Linkable_Format#File_header
ELF_HEADER = {
"EI_MAG": (0x0 | uctypes.ARRAY, 4 | uctypes.UINT8),
"EI_DATA": 0x5 | uctypes.UINT8,
"e_machine": 0x12 | uctypes.UINT16,
}
# "f" is an ELF file opened in binary mode
buf = f.read(uctypes.sizeof(ELF_HEADER, uctypes.LITTLE_ENDIAN))
header = uctypes.struct(uctypes.addressof(buf), ELF_HEADER, uctypes.LITTLE_ENDIAN)
assert header.EI_MAG == b"\x7fELF"
assert header.EI_DATA == 1, "Oops, wrong endianness. Could retry with uctypes.BIG_ENDIAN."
print("machine:", hex(header.e_machine))
# Example 2: In-memory data structure, with pointers
COORD = {
"x": 0 | uctypes.FLOAT32,
"y": 4 | uctypes.FLOAT32,
}
STRUCT1 = {
"data1": 0 | uctypes.UINT8,
"data2": 4 | uctypes.UINT32,
"ptr": (8 | uctypes.PTR, COORD),
}
# Suppose you have address of a structure of type STRUCT1 in "addr"
# uctypes.NATIVE is optional (used by default)
struct1 = uctypes.struct(addr, STRUCT1, uctypes.NATIVE)
print("x:", struct1.ptr[0].x)
# Example 3: Access to CPU registers. Subset of STM32F4xx WWDG block
WWDG_LAYOUT = {
"WWDG_CR": (0, {
# BFUINT32 here means size of the WWDG_CR register
"WDGA": 7 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32,
"T": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32,
}),
"WWDG_CFR": (4, {
"EWI": 9 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32,
"WDGTB": 7 << uctypes.BF_POS | 2 << uctypes.BF_LEN | uctypes.BFUINT32,
"W": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32,
}),
}
WWDG = uctypes.struct(0x40002c00, WWDG_LAYOUT)
WWDG.WWDG_CFR.WDGTB = 0b10
WWDG.WWDG_CR.WDGA = 1
print("Current counter:", WWDG.WWDG_CR.T)
Defining structure layout
-------------------------
Structure layout is defined by a "descriptor" - a Python dictionary which
encodes field names as keys and other properties required to access them as
associated values. Currently, uctypes requires explicit specification of
offsets for each field. Offset are given in bytes from a structure start.
associated values::
{
"field1": <properties>,
"field2": <properties>,
...
}
Currently, ``uctypes`` requires explicit specification of offsets for each
field. Offset are given in bytes from the structure start.
Following are encoding examples for various field types:
@ -33,7 +105,7 @@ Following are encoding examples for various field types:
"field_name": offset | uctypes.UINT32
in other words, value is scalar type identifier ORed with field offset
in other words, the value is a scalar type identifier ORed with a field offset
(in bytes) from the start of the structure.
* Recursive structures::
@ -43,9 +115,11 @@ Following are encoding examples for various field types:
"b1": 1 | uctypes.UINT8,
})
i.e. value is a 2-tuple, first element of which is offset, and second is
i.e. value is a 2-tuple, first element of which is an offset, and second is
a structure descriptor dictionary (note: offsets in recursive descriptors
are relative to the structure it defines).
are relative to the structure it defines). Of course, recursive structures
can be specified not just by a literal dictionary, but by referring to a
structure descriptor dictionary (defined earlier) by name.
* Arrays of primitive types::
@ -53,42 +127,42 @@ Following are encoding examples for various field types:
i.e. value is a 2-tuple, first element of which is ARRAY flag ORed
with offset, and second is scalar element type ORed number of elements
in array.
in the array.
* Arrays of aggregate types::
"arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}),
i.e. value is a 3-tuple, first element of which is ARRAY flag ORed
with offset, second is a number of elements in array, and third is
descriptor of element type.
with offset, second is a number of elements in the array, and third is
a descriptor of element type.
* Pointer to a primitive type::
"ptr": (offset | uctypes.PTR, uctypes.UINT8),
i.e. value is a 2-tuple, first element of which is PTR flag ORed
with offset, and second is scalar element type.
with offset, and second is a scalar element type.
* Pointer to an aggregate type::
"ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}),
i.e. value is a 2-tuple, first element of which is PTR flag ORed
with offset, second is descriptor of type pointed to.
with offset, second is a descriptor of type pointed to.
* Bitfields::
"bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN,
i.e. value is type of scalar value containing given bitfield (typenames are
similar to scalar types, but prefixes with "BF"), ORed with offset for
i.e. value is a type of scalar value containing given bitfield (typenames are
similar to scalar types, but prefixes with ``BF``), ORed with offset for
scalar value containing the bitfield, and further ORed with values for
bit offset and bit length of the bitfield within scalar value, shifted by
BF_POS and BF_LEN positions, respectively. Bitfield position is counted
from the least significant bit, and is the number of right-most bit of a
field (in other words, it's a number of bits a scalar needs to be shifted
right to extract the bitfield).
bit position and bit length of the bitfield within the scalar value, shifted by
BF_POS and BF_LEN bits, respectively. A bitfield position is counted
from the least significant bit of the scalar (having position of 0), and
is the number of right-most bit of a field (in other words, it's a number
of bits a scalar needs to be shifted right to extract the bitfield).
In the example above, first a UINT16 value will be extracted at offset 0
(this detail may be important when accessing hardware registers, where
@ -128,10 +202,11 @@ Module contents
Layout type for a native structure - with data endianness and alignment
conforming to the ABI of the system on which MicroPython runs.
.. function:: sizeof(struct)
.. function:: sizeof(struct, layout_type=NATIVE)
Return size of data structure in bytes. Argument can be either structure
class or specific instantiated structure object (or its aggregate field).
Return size of data structure in bytes. The *struct* argument can be
either a structure class or a specific instantiated structure object
(or its aggregate field).
.. function:: addressof(obj)
@ -153,6 +228,35 @@ Module contents
so it can be both written too, and you will access current value
at the given memory address.
.. data:: UINT8
INT8
UINT16
INT16
UINT32
INT32
UINT64
INT64
Integer types for structure descriptors. Constants for 8, 16, 32,
and 64 bit types are provided, both signed and unsigned.
.. data:: FLOAT32
FLOAT64
Floating-point types for structure descriptors.
.. data:: VOID
``VOID`` is an alias for ``UINT8``, and is provided to conviniently define
C's void pointers: ``(uctypes.PTR, uctypes.VOID)``.
.. data:: PTR
ARRAY
Type constants for pointers and arrays. Note that there is no explicit
constant for structures, it's implicit: an aggregate type without ``PTR``
or ``ARRAY`` flags is a structure.
Structure descriptors and instantiating structure objects
---------------------------------------------------------
@ -165,7 +269,7 @@ following sources:
system. Lookup these addresses in datasheet for a particular MCU/SoC.
* As a return value from a call to some FFI (Foreign Function Interface)
function.
* From uctypes.addressof(), when you want to pass arguments to an FFI
* From `uctypes.addressof()`, when you want to pass arguments to an FFI
function, or alternatively, to access some data for I/O (for example,
data read from a file or network socket).
@ -183,30 +287,41 @@ the standard subscript operator ``[]`` - both read and assigned to.
If a field is a pointer, it can be dereferenced using ``[0]`` syntax
(corresponding to C ``*`` operator, though ``[0]`` works in C too).
Subscripting a pointer with other integer values but 0 are supported too,
Subscripting a pointer with other integer values but 0 are also supported,
with the same semantics as in C.
Summing up, accessing structure fields generally follows C syntax,
Summing up, accessing structure fields generally follows the C syntax,
except for pointer dereference, when you need to use ``[0]`` operator
instead of ``*``.
Limitations
-----------
Accessing non-scalar fields leads to allocation of intermediate objects
1. Accessing non-scalar fields leads to allocation of intermediate objects
to represent them. This means that special care should be taken to
layout a structure which needs to be accessed when memory allocation
is disabled (e.g. from an interrupt). The recommendations are:
* Avoid nested structures. For example, instead of
* Avoid accessing nested structures. For example, instead of
``mcu_registers.peripheral_a.register1``, define separate layout
descriptors for each peripheral, to be accessed as
``peripheral_a.register1``.
* Avoid other non-scalar data, like array. For example, instead of
``peripheral_a.register[0]`` use ``peripheral_a.register0``.
``peripheral_a.register1``. Or just cache a particular peripheral:
``peripheral_a = mcu_registers.peripheral_a``. If a register
consists of multiple bitfields, you would need to cache references
to a particular register: ``reg_a = mcu_registers.peripheral_a.reg_a``.
* Avoid other non-scalar data, like arrays. For example, instead of
``peripheral_a.register[0]`` use ``peripheral_a.register0``. Again,
an alternative is to cache intermediate values, e.g.
``register0 = peripheral_a.register[0]``.
Note that these recommendations will lead to decreased readability
and conciseness of layouts, so they should be used only if the need
to access structure fields without allocation is anticipated (it's
even possible to define 2 parallel layouts - one for normal usage,
and a restricted one to use when memory allocation is prohibited).
2. Range of offsets supported by the ``uctypes`` module is limited.
The exact range supported is considered an implementation detail,
and the general suggestion is to split structure definitions to
cover from a few kilobytes to a few dozen of kilobytes maximum.
In most cases, this is a natural situation anyway, e.g. it doesn't make
sense to define all registers of an MCU (spread over 32-bit address
space) in one structure, but rather a peripheral block by peripheral
block. In some extreme cases, you may need to split a structure in
several parts artificially (e.g. if accessing native data structure
with multi-megabyte array in the middle, though that would be a very
synthetic case).

View File

@ -47,13 +47,18 @@ Methods
*eventmask* defaults to ``uselect.POLLIN | uselect.POLLOUT``.
It is OK to call this function multiple times for the same *obj*.
Successive calls will update *obj*'s eventmask to the value of
*eventmask* (i.e. will behave as `modify()`).
.. method:: poll.unregister(obj)
Unregister *obj* from polling.
.. method:: poll.modify(obj, eventmask)
Modify the *eventmask* for *obj*.
Modify the *eventmask* for *obj*. If *obj* is not registered, `OSError`
is raised with error of ENOENT.
.. method:: poll.poll(timeout=-1)

View File

@ -1,336 +0,0 @@
*******************************
:mod:`usocket` -- socket module
*******************************
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: usocket
:synopsis: socket module
|see_cpython_module| :mod:`cpython:socket`.
This module provides access to the BSD socket interface.
.. admonition:: Difference to CPython
:class: attention
For efficiency and consistency, socket objects in MicroPython implement a ``stream``
(file-like) interface directly. In CPython, you need to convert a socket to
a file-like object using `makefile()` method. This method is still supported
by MicroPython (but is a no-op), so where compatibility with CPython matters,
be sure to use it.
Socket address format(s)
------------------------
The native socket address format of the ``usocket`` module is an opaque data type
returned by `getaddrinfo` function, which must be used to resolve textual address
(including numeric addresses)::
sockaddr = usocket.getaddrinfo('www.micropython.org', 80)[0][-1]
# You must use getaddrinfo() even for numeric addresses
sockaddr = usocket.getaddrinfo('127.0.0.1', 80)[0][-1]
# Now you can use that address
sock.connect(addr)
Using `getaddrinfo` is the most efficient (both in terms of memory and processing
power) and portable way to work with addresses.
However, ``socket`` module (note the difference with native MicroPython
``usocket`` module described here) provides CPython-compatible way to specify
addresses using tuples, as described below.
Summing up:
* Always use `getaddrinfo` when writing portable applications.
* Tuple addresses described below can be used as a shortcut for
quick hacks and interactive use, if your port supports them.
Tuple address format for ``socket`` module:
* IPv4: *(ipv4_address, port)*, where *ipv4_address* is a string with
dot-notation numeric IPv4 address, e.g. ``"8.8.8.8"``, and *port* is and
integer port number in the range 1-65535. Note the domain names are not
accepted as *ipv4_address*, they should be resolved first using
`usocket.getaddrinfo()`.
* IPv6: *(ipv6_address, port, flowinfo, scopeid)*, where *ipv6_address*
is a string with colon-notation numeric IPv6 address, e.g. ``"2001:db8::1"``,
and *port* is an integer port number in the range 1-65535. *flowinfo*
must be 0. *scopeid* is the interface scope identifier for link-local
addresses. Note the domain names are not accepted as *ipv6_address*,
they should be resolved first using `usocket.getaddrinfo()`.
Functions
---------
.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP)
Create a new socket using the given address family, socket type and
protocol number. Note that specifying *proto* in most cases is not
required (and not recommended, as some MicroPython ports may omit
``IPPROTO_*`` constants). Instead, *type* argument will select needed
protocol automatically::
# Create STREAM TCP socket
socket(AF_INET, SOCK_STREAM)
# Create DGRAM UDP socket
socket(AF_INET, SOCK_DGRAM)
.. function:: getaddrinfo(host, port)
Translate the host/port argument into a sequence of 5-tuples that contain all the
necessary arguments for creating a socket connected to that service. The list of
5-tuples has following structure::
(family, type, proto, canonname, sockaddr)
The following example shows how to connect to a given url::
s = usocket.socket()
s.connect(usocket.getaddrinfo('www.micropython.org', 80)[0][-1])
.. admonition:: Difference to CPython
:class: attention
CPython raises a ``socket.gaierror`` exception (`OSError` subclass) in case
of error in this function. MicroPython doesn't have ``socket.gaierror``
and raises OSError directly. Note that error numbers of `getaddrinfo()`
form a separate namespace and may not match error numbers from
:py:mod:`uerrno` module. To distinguish `getaddrinfo()` errors, they are
represented by negative numbers, whereas standard system errors are
positive numbers (error numbers are accessible using ``e.args[0]`` property
from an exception object). The use of negative values is a provisional
detail which may change in the future.
.. function:: inet_ntop(af, bin_addr)
Convert a binary network address *bin_addr* of the given address family *af*
to a textual representation::
>>> usocket.inet_ntop(usocket.AF_INET, b"\x7f\0\0\1")
'127.0.0.1'
.. function:: inet_pton(af, txt_addr)
Convert a textual network address *txt_addr* of the given address family *af*
to a binary representation::
>>> usocket.inet_pton(usocket.AF_INET, "1.2.3.4")
b'\x01\x02\x03\x04'
Constants
---------
.. data:: AF_INET
AF_INET6
Address family types. Availability depends on a particular ``MicroPython port``.
.. data:: SOCK_STREAM
SOCK_DGRAM
Socket types.
.. data:: IPPROTO_UDP
IPPROTO_TCP
IP protocol numbers. Availability depends on a particular ``MicroPython port``.
Note that you don't need to specify these in a call to `usocket.socket()`,
because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and
`SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants
is as an argument to `usocket.socket.setsockopt()`.
.. data:: usocket.SOL_*
Socket option levels (an argument to `usocket.socket.setsockopt()`). The exact
inventory depends on a ``MicroPython port``.
.. data:: usocket.SO_*
Socket options (an argument to `usocket.socket.setsockopt()`). The exact
inventory depends on a ``MicroPython port``.
Constants specific to WiPy:
.. data:: IPPROTO_SEC
Special protocol value to create SSL-compatible socket.
class socket
============
Methods
-------
.. method:: socket.close()
Mark the socket closed and release all resources. Once that happens, all future operations
on the socket object will fail. The remote end will receive EOF indication if
supported by protocol.
Sockets are automatically closed when they are garbage-collected, but it is recommended
to `close()` them explicitly as soon you finished working with them.
.. method:: socket.bind(address)
Bind the socket to *address*. The socket must not already be bound.
.. method:: socket.listen([backlog])
Enable a server to accept connections. If *backlog* is specified, it must be at least 0
(if it's lower, it will be set to 0); and specifies the number of unaccepted connections
that the system will allow before refusing new connections. If not specified, a default
reasonable value is chosen.
.. method:: socket.accept()
Accept a connection. The socket must be bound to an address and listening for connections.
The return value is a pair (conn, address) where conn is a new socket object usable to send
and receive data on the connection, and address is the address bound to the socket on the
other end of the connection.
.. method:: socket.connect(address)
Connect to a remote socket at *address*.
.. method:: socket.send(bytes)
Send data to the socket. The socket must be connected to a remote socket.
Returns number of bytes sent, which may be smaller than the length of data
("short write").
.. method:: socket.sendall(bytes)
Send all data to the socket. The socket must be connected to a remote socket.
Unlike `send()`, this method will try to send all of data, by sending data
chunk by chunk consecutively.
The behavior of this method on non-blocking sockets is undefined. Due to this,
on MicroPython, it's recommended to use `write()` method instead, which
has the same "no short writes" policy for blocking sockets, and will return
number of bytes sent on non-blocking sockets.
.. method:: socket.recv(bufsize)
Receive data from the socket. The return value is a bytes object representing the data
received. The maximum amount of data to be received at once is specified by bufsize.
.. method:: socket.sendto(bytes, address)
Send data to the socket. The socket should not be connected to a remote socket, since the
destination socket is specified by *address*.
.. method:: socket.recvfrom(bufsize)
Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a
bytes object representing the data received and *address* is the address of the socket sending
the data.
.. method:: socket.setsockopt(level, optname, value)
Set the value of the given socket option. The needed symbolic constants are defined in the
socket module (SO_* etc.). The *value* can be an integer or a bytes-like object representing
a buffer.
.. method:: socket.settimeout(value)
**Note**: Not every port supports this method, see below.
Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
will raise an `OSError` exception if the timeout period value has elapsed before the operation has
completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
is put in blocking mode.
Not every ``MicroPython port`` supports this method. A more portable and
generic solution is to use `uselect.poll` object. This allows to wait on
multiple objects at the same time (and not just on sockets, but on generic
``stream`` objects which support polling). Example::
# Instead of:
s.settimeout(1.0) # time in seconds
s.read(10) # may timeout
# Use:
poller = uselect.poll()
poller.register(s, uselect.POLLIN)
res = poller.poll(1000) # time in milliseconds
if not res:
# s is still not ready for input, i.e. operation timed out
.. admonition:: Difference to CPython
:class: attention
CPython raises a ``socket.timeout`` exception in case of timeout,
which is an `OSError` subclass. MicroPython raises an OSError directly
instead. If you use ``except OSError:`` to catch the exception,
your code will work both in MicroPython and CPython.
.. method:: socket.setblocking(flag)
Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
else to blocking mode.
This method is a shorthand for certain `settimeout()` calls:
* ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)``
* ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)``
.. method:: socket.makefile(mode='rb', buffering=0)
Return a file object associated with the socket. The exact returned type depends on the arguments
given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb').
CPython's arguments: *encoding*, *errors* and *newline* are not supported.
.. admonition:: Difference to CPython
:class: attention
As MicroPython doesn't support buffered streams, values of *buffering*
parameter is ignored and treated as if it was 0 (unbuffered).
.. admonition:: Difference to CPython
:class: attention
Closing the file object returned by makefile() WILL close the
original socket as well.
.. method:: socket.read([size])
Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it
reads all data available from the socket until EOF; as such the method will not return until
the socket is closed. This function tries to read as much data as
requested (no "short reads"). This may be not possible with
non-blocking socket though, and then less data will be returned.
.. method:: socket.readinto(buf[, nbytes])
Read bytes into the *buf*. If *nbytes* is specified then read at most
that many bytes. Otherwise, read at most *len(buf)* bytes. Just as
`read()`, this method follows "no short reads" policy.
Return value: number of bytes read and stored into *buf*.
.. method:: socket.readline()
Read a line, ending in a newline character.
Return value: the line read.
.. method:: socket.write(buf)
Write the buffer of bytes to the socket. This function will try to
write all data to a socket (no "short writes"). This may be not possible
with a non-blocking socket though, and returned value will be less than
the length of *buf*.
Return value: number of bytes written.
.. exception:: usocket.error
MicroPython does NOT have this exception.
.. admonition:: Difference to CPython
:class: attention
CPython used to have a ``socket.error`` exception which is now deprecated,
and is an alias of `OSError`. In MicroPython, use `OSError` directly.

View File

@ -1,50 +0,0 @@
:mod:`ussl` -- SSL/TLS module
=============================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: ussl
:synopsis: TLS/SSL wrapper for socket objects
|see_cpython_module| :mod:`cpython:ssl`.
This module provides access to Transport Layer Security (previously and
widely known as “Secure Sockets Layer”) encryption and peer authentication
facilities for network sockets, both client-side and server-side.
Functions
---------
.. function:: ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
Takes a ``stream`` *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type),
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
an SSL context. Returned object has the usual ``stream`` interface methods like
``read()``, ``write()``, etc. In MicroPython, the returned object does not expose
socket interface and methods like ``recv()``, ``send()``. In particular, a
server-side SSL socket should be created from a normal socket returned from
:meth:`~usocket.socket.accept()` on a non-SSL listening server socket.
Depending on the underlying module implementation in a particular
``MicroPython port``, some or all keyword arguments above may be not supported.
.. warning::
Some implementations of ``ussl`` module do NOT validate server certificates,
which makes an SSL connection established prone to man-in-the-middle attacks.
Exceptions
----------
.. data:: ssl.SSLError
This exception does NOT exist. Instead its base class, OSError, is used.
Constants
---------
.. data:: ussl.CERT_NONE
ussl.CERT_OPTIONAL
ussl.CERT_REQUIRED
Supported values for *cert_reqs* parameter.

17
docs/static/filter.css vendored Normal file
View File

@ -0,0 +1,17 @@
#support-matrix-filter-block { position: relative; }
#support-matrix-filter {
width: 100%;
}
#support-matrix-filter-num {
position: absolute;
right: 10px;
top: 4px;
}
.support-matrix-table .this_module code,
.support-matrix-table .this_module span {
background: black;
color: white;
}
.support-matrix-table .board_hidden {
display: none;
}

86
docs/static/filter.js vendored Normal file
View File

@ -0,0 +1,86 @@
$(() => {
var urlTimeout = null;
function setURL(query, value) {
clearTimeout(urlTimeout);
urlTimeout = setTimeout(function() {
var url = new URL(window.location.href);
console.log(query,value,value.length,!value.length);
if (!value.length) {
console.log
url.searchParams.delete(query);
} else if (Array.isArray(value)) {
url.searchParams.delete(query);
value.forEach(function(v) {
url.searchParams.append(query, v);
})
} else {
url.searchParams.set(query, value);
}
window.history.pushState(null, document.title, url.href);
}, 1000);
}
function handlePageLoad() {
var url = new URL(window.location.href);
//get values from URL
var filters = url.searchParams.getAll('filter');
search_terms = filters.join(" ");
$("#support-matrix-filter").val(search_terms);
run_filter();
}
function filter_boards(search_string) {
$(".board_hidden").removeClass("board_hidden");
$(".this_module").removeClass("this_module");
var nboards = $(".support-matrix-table tbody tr").length;
if(search_string.trim() == "") {
$("#support-matrix-filter-num").html("(all)");
setURL("filter",[]);
return;
}
var list_search = search_string.split(" ").filter(i => i);
var nvisible = 0;
$(".support-matrix-table tbody tr").each( (index,item) => {
var name = $(item).find("td:first-child p").html();
var modules = $(item).find("a.reference.internal");
var matching_all = true;
//
list_search.forEach((sstring) => {
var matching = (sstring[0] == "-");
for(var modi = 0; modi < modules.length; ++modi) {
module = modules[modi];
var mod_name = module.firstChild.firstChild.textContent;
if(sstring[0] == "-") {
if(mod_name.match(sstring.substr(1))) {
matching = false;
break;
}
} else {
if(mod_name.match(sstring)) {
$(module).addClass("this_module");
matching = true;
}
}
}
matching_all = matching_all && matching;
});
if(!matching_all) {
$(item).addClass("board_hidden");
} else {
nvisible += 1;
}
});
$("#support-matrix-filter-num").html(`(${nvisible}/${nboards})`);
setURL("filter",list_search);
}
function run_filter() {
var search_string = $("#support-matrix-filter").val();
filter_boards(search_string);
}
$("#support-matrix-filter").on("keyup", run_filter);
// $(document).on("keyup", "#support-matrix-filter", run_filter);
handlePageLoad();
});

View File

@ -1,203 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* SPDX-FileCopyrightText: Copyright (c) 2017-2018 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 "drivers/bus/qspi.h"
#define CS_LOW(self) mp_hal_pin_write(self->cs, 0)
#define CS_HIGH(self) mp_hal_pin_write(self->cs, 1)
#ifdef MICROPY_HW_SOFTQSPI_SCK_LOW
// Use externally provided functions for SCK control and IO reading
#define SCK_LOW(self) MICROPY_HW_SOFTQSPI_SCK_LOW(self)
#define SCK_HIGH(self) MICROPY_HW_SOFTQSPI_SCK_HIGH(self)
#define NIBBLE_READ(self) MICROPY_HW_SOFTQSPI_NIBBLE_READ(self)
#else
// Use generic pin functions for SCK control and IO reading
#define SCK_LOW(self) mp_hal_pin_write(self->clk, 0)
#define SCK_HIGH(self) mp_hal_pin_write(self->clk, 1)
#define NIBBLE_READ(self) ( \
mp_hal_pin_read(self->io0) \
| (mp_hal_pin_read(self->io1) << 1) \
| (mp_hal_pin_read(self->io2) << 2) \
| (mp_hal_pin_read(self->io3) << 3))
#endif
STATIC void nibble_write(mp_soft_qspi_obj_t *self, uint8_t v) {
mp_hal_pin_write(self->io0, v & 1);
mp_hal_pin_write(self->io1, (v >> 1) & 1);
mp_hal_pin_write(self->io2, (v >> 2) & 1);
mp_hal_pin_write(self->io3, (v >> 3) & 1);
}
STATIC int mp_soft_qspi_ioctl(void *self_in, uint32_t cmd) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
switch (cmd) {
case MP_QSPI_IOCTL_INIT:
mp_hal_pin_high(self->cs);
mp_hal_pin_output(self->cs);
// Configure pins
mp_hal_pin_write(self->clk, 0);
mp_hal_pin_output(self->clk);
// mp_hal_pin_write(self->clk, 1);
mp_hal_pin_output(self->io0);
mp_hal_pin_input(self->io1);
mp_hal_pin_write(self->io2, 1);
mp_hal_pin_output(self->io2);
mp_hal_pin_write(self->io3, 1);
mp_hal_pin_output(self->io3);
break;
}
return 0; // success
}
STATIC void mp_soft_qspi_transfer(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest) {
// Will run as fast as possible, limited only by CPU speed and GPIO time
mp_hal_pin_input(self->io1);
mp_hal_pin_output(self->io0);
if (self->io3) {
mp_hal_pin_write(self->io2, 1);
mp_hal_pin_output(self->io2);
mp_hal_pin_write(self->io3, 1);
mp_hal_pin_output(self->io3);
}
if (src) {
for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i];
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->io0, (data_out >> 7) & 1);
mp_hal_pin_write(self->clk, 1);
data_in = (data_in << 1) | mp_hal_pin_read(self->io1);
mp_hal_pin_write(self->clk, 0);
}
if (dest != NULL) {
dest[i] = data_in;
}
}
} else {
for (size_t i = 0; i < len; ++i) {
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j) {
mp_hal_pin_write(self->clk, 1);
data_in = (data_in << 1) | mp_hal_pin_read(self->io1);
mp_hal_pin_write(self->clk, 0);
}
if (dest != NULL) {
dest[i] = data_in;
}
}
}
}
STATIC void mp_soft_qspi_qread(mp_soft_qspi_obj_t *self, size_t len, uint8_t *buf) {
// Make all IO lines input
mp_hal_pin_input(self->io2);
mp_hal_pin_input(self->io3);
mp_hal_pin_input(self->io0);
mp_hal_pin_input(self->io1);
// Will run as fast as possible, limited only by CPU speed and GPIO time
while (len--) {
SCK_HIGH(self);
uint8_t data_in = NIBBLE_READ(self);
SCK_LOW(self);
SCK_HIGH(self);
*buf++ = (data_in << 4) | NIBBLE_READ(self);
SCK_LOW(self);
}
}
STATIC void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint8_t *buf) {
// Make all IO lines output
mp_hal_pin_output(self->io2);
mp_hal_pin_output(self->io3);
mp_hal_pin_output(self->io0);
mp_hal_pin_output(self->io1);
// Will run as fast as possible, limited only by CPU speed and GPIO time
for (size_t i = 0; i < len; ++i) {
nibble_write(self, buf[i] >> 4);
SCK_HIGH(self);
SCK_LOW(self);
nibble_write(self, buf[i]);
SCK_HIGH(self);
SCK_LOW(self);
}
// mp_hal_pin_input(self->io1);
}
STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
uint32_t cmd_buf = cmd | data << 8;
CS_LOW(self);
mp_soft_qspi_transfer(self, 1 + len, (uint8_t *)&cmd_buf, NULL);
CS_HIGH(self);
}
STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
uint8_t cmd_buf[4] = {cmd, addr >> 16, addr >> 8, addr};
CS_LOW(self);
mp_soft_qspi_transfer(self, 4, cmd_buf, NULL);
mp_soft_qspi_transfer(self, len, src, NULL);
CS_HIGH(self);
}
STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
uint32_t cmd_buf = cmd;
CS_LOW(self);
mp_soft_qspi_transfer(self, 1 + len, (uint8_t *)&cmd_buf, (uint8_t *)&cmd_buf);
CS_HIGH(self);
return cmd_buf >> 8;
}
STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t *)self_in;
uint8_t cmd_buf[7] = {cmd, addr >> 16, addr >> 8, addr};
CS_LOW(self);
mp_soft_qspi_transfer(self, 1, cmd_buf, NULL);
mp_soft_qspi_qwrite(self, 6, &cmd_buf[1]); // 3 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles)
mp_soft_qspi_qread(self, len, dest);
CS_HIGH(self);
}
const mp_qspi_proto_t mp_soft_qspi_proto = {
.ioctl = mp_soft_qspi_ioctl,
.write_cmd_data = mp_soft_qspi_write_cmd_data,
.write_cmd_addr_data = mp_soft_qspi_write_cmd_addr_data,
.read_cmd = mp_soft_qspi_read_cmd,
.read_cmd_qaddr_qdata = mp_soft_qspi_read_cmd_qaddr_qdata,
};

View File

@ -1,105 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* SPDX-FileCopyrightText: Copyright (c) 2016-2018 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 "drivers/bus/spi.h"
int mp_soft_spi_ioctl(void *self_in, uint32_t cmd) {
mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t *)self_in;
switch (cmd) {
case MP_SPI_IOCTL_INIT:
mp_hal_pin_write(self->sck, self->polarity);
mp_hal_pin_output(self->sck);
mp_hal_pin_output(self->mosi);
mp_hal_pin_input(self->miso);
break;
case MP_SPI_IOCTL_DEINIT:
break;
}
return 0;
}
void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t *)self_in;
uint32_t delay_half = self->delay_half;
// only MSB transfer is implemented
// If a port defines MICROPY_HW_SOFTSPI_MIN_DELAY, and the configured
// delay_half is equal to this value, then the software SPI implementation
// will run as fast as possible, limited only by CPU speed and GPIO time.
#ifdef MICROPY_HW_SOFTSPI_MIN_DELAY
if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) {
for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i];
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
mp_hal_pin_write(self->sck, 1 - self->polarity);
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
mp_hal_pin_write(self->sck, self->polarity);
}
if (dest != NULL) {
dest[i] = data_in;
}
}
return;
}
#endif
for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i];
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
if (self->phase == 0) {
mp_hal_delay_us_fast(delay_half);
mp_hal_pin_write(self->sck, 1 - self->polarity);
} else {
mp_hal_pin_write(self->sck, 1 - self->polarity);
mp_hal_delay_us_fast(delay_half);
}
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
if (self->phase == 0) {
mp_hal_delay_us_fast(delay_half);
mp_hal_pin_write(self->sck, self->polarity);
} else {
mp_hal_pin_write(self->sck, self->polarity);
mp_hal_delay_us_fast(delay_half);
}
}
if (dest != NULL) {
dest[i] = data_in;
}
}
}
const mp_spi_proto_t mp_soft_spi_proto = {
.ioctl = mp_soft_spi_ioctl,
.transfer = mp_soft_spi_transfer,
};

View File

@ -1,6 +0,0 @@
This is the driver for the WIZnet5x00 series of Ethernet controllers.
Adapted for MicroPython.
Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary
Taken on: 30 August 2014

View File

@ -1,718 +0,0 @@
//*****************************************************************************
//
//! \file socket.c
//! \brief SOCKET APIs Implements file.
//! \details SOCKET APIs like as Berkeley Socket APIs.
//! \version 1.0.3
//! \date 2013/10/21
//! \par Revision history
//! <2018/10/09> Nick Moore fixes for CircuitPython
//! <2014/05/01> V1.0.3. Refer to M20140501
//! 1. Implicit type casting -> Explicit type casting.
//! 2. replace 0x01 with PACK_REMAINED in recvfrom()
//! 3. Validation a destination ip in connect() & sendto():
//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address.
//! Copy 4 byte addr value into temporary uint32 variable and then compares it.
//! <2013/12/20> V1.0.2 Refer to M20131220
//! Remove Warning.
//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104".
//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT)
//! <2013/10/21> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
#include <string.h>
#include "py/mpthread.h"
#include "socket.h"
#define SOCK_ANY_PORT_NUM 0xC000;
static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
static uint16_t sock_io_mode = 0;
static uint16_t sock_is_sending = 0;
static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
#if _WIZCHIP_ == 5200
static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,};
#endif
#define CHECK_SOCKNUM() \
do{ \
if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \
}while(0); \
#define CHECK_SOCKMODE(mode) \
do{ \
if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \
}while(0); \
#define CHECK_SOCKINIT() \
do{ \
if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
}while(0); \
#define CHECK_SOCKDATA() \
do{ \
if(len == 0) return SOCKERR_DATALEN; \
}while(0); \
void WIZCHIP_EXPORT(socket_reset)(void) {
sock_any_port = SOCK_ANY_PORT_NUM;
sock_io_mode = 0;
sock_is_sending = 0;
/*
memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t));
*/
#if _WIZCHIP_ == 5200
memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
#endif
}
int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
{
CHECK_SOCKNUM();
switch(protocol)
{
case Sn_MR_TCP :
case Sn_MR_UDP :
case Sn_MR_MACRAW :
break;
#if ( _WIZCHIP_ < 5200 )
case Sn_MR_IPRAW :
case Sn_MR_PPPoE :
break;
#endif
default :
return SOCKERR_SOCKMODE;
}
if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
#if _WIZCHIP_ == 5200
if(flag & 0x10) return SOCKERR_SOCKFLAG;
#endif
if(flag != 0)
{
switch(protocol)
{
case Sn_MR_TCP:
if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
break;
case Sn_MR_UDP:
if(flag & SF_IGMP_VER2)
{
if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
}
#if _WIZCHIP_ == 5500
if(flag & SF_UNI_BLOCK)
{
if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
}
#endif
break;
default:
break;
}
}
WIZCHIP_EXPORT(close)(sn);
setSn_MR(sn, (protocol | (flag & 0xF0)));
if(!port)
{
port = sock_any_port++;
if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
}
setSn_PORT(sn,port);
setSn_CR(sn,Sn_CR_OPEN);
while(getSn_CR(sn));
sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
sock_is_sending &= ~(1<<sn);
sock_remained_size[sn] = 0;
sock_pack_info[sn] = 0;
while(getSn_SR(sn) == SOCK_CLOSED);
return (int8_t)sn;
}
int8_t WIZCHIP_EXPORT(close)(uint8_t sn)
{
CHECK_SOCKNUM();
setSn_CR(sn,Sn_CR_CLOSE);
/* wait to process the command... */
while( getSn_CR(sn) );
/* clear all interrupt of the socket. */
setSn_IR(sn, 0xFF);
sock_is_sending &= ~(1<<sn);
sock_remained_size[sn] = 0;
sock_pack_info[sn] = 0;
while(getSn_SR(sn) != SOCK_CLOSED);
return SOCK_OK;
}
int8_t WIZCHIP_EXPORT(listen)(uint8_t sn)
{
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKINIT();
setSn_CR(sn,Sn_CR_LISTEN);
while(getSn_CR(sn));
while(getSn_SR(sn) != SOCK_LISTEN)
{
if(getSn_CR(sn) == SOCK_CLOSED)
{
WIZCHIP_EXPORT(close)(sn);
return SOCKERR_SOCKCLOSED;
}
}
return SOCK_OK;
}
int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port)
{
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKINIT();
//M20140501 : For avoiding fatal error on memory align mismatched
//if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
{
uint32_t taddr;
taddr = ((uint32_t)addr[0] & 0x000000FF);
taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
if (taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
}
//
if(port == 0) return SOCKERR_PORTZERO;
setSn_DIPR(sn,addr);
setSn_DPORT(sn,port);
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR(wizchip_getsubn());
#endif
setSn_CR(sn,Sn_CR_CONNECT);
while(getSn_CR(sn));
if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
while(getSn_SR(sn) != SOCK_ESTABLISHED)
{
if (getSn_SR(sn) == SOCK_CLOSED) {
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR((uint8_t*)"\x00\x00\x00\x00");
#endif
return SOCKERR_SOCKCLOSED;
}
if (getSn_IR(sn) & Sn_IR_TIMEOUT)
{
setSn_IR(sn, Sn_IR_TIMEOUT);
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR((uint8_t*)"\x00\x00\x00\x00");
#endif
return SOCKERR_TIMEOUT;
}
MICROPY_THREAD_YIELD();
}
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR((uint8_t*)"\x00\x00\x00\x00");
#endif
return SOCK_OK;
}
int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn)
{
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
setSn_CR(sn,Sn_CR_DISCON);
/* wait to process the command... */
while(getSn_CR(sn));
sock_is_sending &= ~(1<<sn);
if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
while(getSn_SR(sn) != SOCK_CLOSED)
{
if(getSn_IR(sn) & Sn_IR_TIMEOUT)
{
WIZCHIP_EXPORT(close)(sn);
return SOCKERR_TIMEOUT;
}
}
return SOCK_OK;
}
int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len)
{
uint8_t tmp=0;
uint16_t freesize=0;
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKDATA();
tmp = getSn_SR(sn);
if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
if( sock_is_sending & (1<<sn) )
{
tmp = getSn_IR(sn);
if(tmp & Sn_IR_SENDOK)
{
setSn_IR(sn, Sn_IR_SENDOK);
#if _WIZCHIP_ == 5200
if(getSn_TX_RD(sn) != sock_next_rd[sn])
{
setSn_CR(sn,Sn_CR_SEND);
while(getSn_CR(sn));
return SOCKERR_BUSY;
}
#endif
sock_is_sending &= ~(1<<sn);
}
else if(tmp & Sn_IR_TIMEOUT)
{
WIZCHIP_EXPORT(close)(sn);
return SOCKERR_TIMEOUT;
}
else return SOCK_BUSY;
}
freesize = getSn_TxMAX(sn);
if (len > freesize) len = freesize; // check size not to exceed MAX size.
while(1)
{
freesize = getSn_TX_FSR(sn);
tmp = getSn_SR(sn);
if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
{
WIZCHIP_EXPORT(close)(sn);
return SOCKERR_SOCKSTATUS;
}
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
if(len <= freesize) break;
MICROPY_THREAD_YIELD();
}
wiz_send_data(sn, buf, len);
#if _WIZCHIP_ == 5200
sock_next_rd[sn] = getSn_TX_RD(sn) + len;
#endif
setSn_CR(sn,Sn_CR_SEND);
/* wait to process the command... */
while(getSn_CR(sn));
sock_is_sending |= (1 << sn);
return len;
}
int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len)
{
uint8_t tmp = 0;
uint16_t recvsize = 0;
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKDATA();
recvsize = getSn_RxMAX(sn);
if(recvsize < len) len = recvsize;
while(1)
{
recvsize = getSn_RX_RSR(sn);
tmp = getSn_SR(sn);
if (tmp != SOCK_ESTABLISHED)
{
if(tmp == SOCK_CLOSE_WAIT)
{
if(recvsize != 0) break;
else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
{
// dpgeorge: Getting here seems to be an orderly shutdown of the
// socket, and trying to get POSIX behaviour we return 0 because:
// "If no messages are available to be received and the peer has per
// formed an orderly shutdown, recv() shall return 0".
// TODO this return value clashes with SOCK_BUSY in non-blocking mode.
WIZCHIP_EXPORT(close)(sn);
return 0;
}
}
else
{
WIZCHIP_EXPORT(close)(sn);
return SOCKERR_SOCKSTATUS;
}
}
if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
if(recvsize != 0) break;
MICROPY_THREAD_YIELD();
};
if(recvsize < len) len = recvsize;
wiz_recv_data(sn, buf, len);
setSn_CR(sn,Sn_CR_RECV);
while(getSn_CR(sn));
return len;
}
int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
{
uint8_t tmp = 0;
uint16_t freesize = 0;
CHECK_SOCKNUM();
switch(getSn_MR(sn) & 0x0F)
{
case Sn_MR_UDP:
case Sn_MR_MACRAW:
break;
default:
return SOCKERR_SOCKMODE;
}
CHECK_SOCKDATA();
//M20140501 : For avoiding fatal error on memory align mismatched
//if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
if ((addr[0] | addr[1] | addr[2] | addr[3]) == 0) return SOCKERR_IPINVALID;
if(port == 0) return SOCKERR_PORTZERO;
tmp = getSn_SR(sn);
if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
setSn_DIPR(sn,addr);
setSn_DPORT(sn,port);
freesize = getSn_TxMAX(sn);
if (len > freesize) len = freesize; // check size not to exceed MAX size.
while(1)
{
freesize = getSn_TX_FSR(sn);
if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
if(len <= freesize) break;
MICROPY_THREAD_YIELD();
};
wiz_send_data(sn, buf, len);
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR(wizchip_getsubn());
#endif
setSn_CR(sn,Sn_CR_SEND);
/* wait to process the command... */
while(getSn_CR(sn));
while(1)
{
tmp = getSn_IR(sn);
if(tmp & Sn_IR_SENDOK)
{
setSn_IR(sn, Sn_IR_SENDOK);
break;
}
//M:20131104
//else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
else if(tmp & Sn_IR_TIMEOUT)
{
setSn_IR(sn, Sn_IR_TIMEOUT);
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR((uint8_t*)"\x00\x00\x00\x00");
#endif
return SOCKERR_TIMEOUT;
}
////////////
MICROPY_THREAD_YIELD();
}
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR((uint8_t*)"\x00\x00\x00\x00");
#endif
return len;
}
int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
{
uint8_t mr;
uint8_t head[8];
uint16_t pack_len=0;
CHECK_SOCKNUM();
//CHECK_SOCKMODE(Sn_MR_UDP);
switch((mr=getSn_MR(sn)) & 0x0F)
{
case Sn_MR_UDP:
case Sn_MR_MACRAW:
break;
#if ( _WIZCHIP_ < 5200 )
case Sn_MR_IPRAW:
case Sn_MR_PPPoE:
break;
#endif
default:
return SOCKERR_SOCKMODE;
}
CHECK_SOCKDATA();
if(sock_remained_size[sn] == 0)
{
while(1)
{
pack_len = getSn_RX_RSR(sn);
if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
if(pack_len != 0) break;
MICROPY_THREAD_YIELD();
};
}
sock_pack_info[sn] = PACK_COMPLETED;
switch (mr & 0x07)
{
case Sn_MR_UDP :
if(sock_remained_size[sn] == 0)
{
wiz_recv_data(sn, head, 8);
setSn_CR(sn,Sn_CR_RECV);
while(getSn_CR(sn));
// read peer's IP address, port number & packet length
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = head[4];
*port = (*port << 8) + head[5];
sock_remained_size[sn] = head[6];
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
sock_pack_info[sn] = PACK_FIRST;
}
if(len < sock_remained_size[sn]) pack_len = len;
else pack_len = sock_remained_size[sn];
//
// Need to packet length check (default 1472)
//
wiz_recv_data(sn, buf, pack_len); // data copy.
break;
case Sn_MR_MACRAW :
if(sock_remained_size[sn] == 0)
{
wiz_recv_data(sn, head, 2);
setSn_CR(sn,Sn_CR_RECV);
while(getSn_CR(sn));
// read peer's IP address, port number & packet length
sock_remained_size[sn] = head[0];
sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1];
sock_remained_size[sn] -= 2; // len includes 2 len bytes
if(sock_remained_size[sn] > 1514)
{
WIZCHIP_EXPORT(close)(sn);
return SOCKFATAL_PACKLEN;
}
sock_pack_info[sn] = PACK_FIRST;
}
if(len < sock_remained_size[sn]) pack_len = len;
else pack_len = sock_remained_size[sn];
wiz_recv_data(sn,buf,pack_len);
break;
#if ( _WIZCHIP_ < 5200 )
case Sn_MR_IPRAW:
if(sock_remained_size[sn] == 0)
{
wiz_recv_data(sn, head, 6);
setSn_CR(sn,Sn_CR_RECV);
while(getSn_CR(sn));
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
sock_remained_size[sn] = head[4];
sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
sock_pack_info[sn] = PACK_FIRST;
}
//
// Need to packet length check
//
if(len < sock_remained_size[sn]) pack_len = len;
else pack_len = sock_remained_size[sn];
wiz_recv_data(sn, buf, pack_len); // data copy.
break;
#endif
default:
wiz_recv_ignore(sn, pack_len); // data copy.
sock_remained_size[sn] = pack_len;
break;
}
setSn_CR(sn,Sn_CR_RECV);
/* wait to process the command... */
while(getSn_CR(sn)) ;
sock_remained_size[sn] -= pack_len;
//M20140501 : replace 0x01 with PACK_REMAINED
//if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED;
//
return pack_len;
}
int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg)
{
uint8_t tmp = 0;
CHECK_SOCKNUM();
switch(cstype)
{
case CS_SET_IOMODE:
tmp = *((uint8_t*)arg);
if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1<<sn);
else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn);
else return SOCKERR_ARG;
break;
case CS_GET_IOMODE:
//M20140501 : implict type casting -> explict type casting
//*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
*((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
//
break;
case CS_GET_MAXTXBUF:
*((uint16_t*)arg) = getSn_TxMAX(sn);
break;
case CS_GET_MAXRXBUF:
*((uint16_t*)arg) = getSn_RxMAX(sn);
break;
case CS_CLR_INTERRUPT:
if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
setSn_IR(sn,*(uint8_t*)arg);
break;
case CS_GET_INTERRUPT:
*((uint8_t*)arg) = getSn_IR(sn);
break;
case CS_SET_INTMASK:
if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
setSn_IMR(sn,*(uint8_t*)arg);
break;
case CS_GET_INTMASK:
*((uint8_t*)arg) = getSn_IMR(sn);
default:
return SOCKERR_ARG;
}
return SOCK_OK;
}
int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
{
// M20131220 : Remove warning
//uint8_t tmp;
CHECK_SOCKNUM();
switch(sotype)
{
case SO_TTL:
setSn_TTL(sn,*(uint8_t*)arg);
break;
case SO_TOS:
setSn_TOS(sn,*(uint8_t*)arg);
break;
case SO_MSS:
setSn_MSSR(sn,*(uint16_t*)arg);
break;
case SO_DESTIP:
setSn_DIPR(sn, (uint8_t*)arg);
break;
case SO_DESTPORT:
setSn_DPORT(sn, *(uint16_t*)arg);
break;
#if _WIZCHIP_ != 5100
case SO_KEEPALIVESEND:
CHECK_SOCKMODE(Sn_MR_TCP);
#if _WIZCHIP_ > 5200
if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
#endif
setSn_CR(sn,Sn_CR_SEND_KEEP);
while(getSn_CR(sn) != 0)
{
// M20131220
//if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
if (getSn_IR(sn) & Sn_IR_TIMEOUT)
{
setSn_IR(sn, Sn_IR_TIMEOUT);
return SOCKERR_TIMEOUT;
}
}
break;
#if _WIZCHIP_ > 5200
case SO_KEEPALIVEAUTO:
CHECK_SOCKMODE(Sn_MR_TCP);
setSn_KPALVTR(sn,*(uint8_t*)arg);
break;
#endif
#endif
default:
return SOCKERR_ARG;
}
return SOCK_OK;
}
int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
{
CHECK_SOCKNUM();
switch(sotype)
{
case SO_FLAG:
*(uint8_t*)arg = getSn_MR(sn) & 0xF0;
break;
case SO_TTL:
*(uint8_t*) arg = getSn_TTL(sn);
break;
case SO_TOS:
*(uint8_t*) arg = getSn_TOS(sn);
break;
case SO_MSS:
*(uint8_t*) arg = getSn_MSSR(sn);
case SO_DESTIP:
getSn_DIPR(sn, (uint8_t*)arg);
break;
case SO_DESTPORT:
*(uint16_t*) arg = getSn_DPORT(sn);
break;
#if _WIZCHIP_ > 5200
case SO_KEEPALIVEAUTO:
CHECK_SOCKMODE(Sn_MR_TCP);
*(uint16_t*) arg = getSn_KPALVTR(sn);
break;
#endif
case SO_SENDBUF:
*(uint16_t*) arg = getSn_TX_FSR(sn);
case SO_RECVBUF:
*(uint16_t*) arg = getSn_RX_RSR(sn);
case SO_STATUS:
*(uint8_t*) arg = getSn_SR(sn);
break;
case SO_REMAINSIZE:
if(getSn_MR(sn) == Sn_MR_TCP)
*(uint16_t*)arg = getSn_RX_RSR(sn);
else
*(uint16_t*)arg = sock_remained_size[sn];
break;
case SO_PACKINFO:
CHECK_SOCKMODE(Sn_MR_TCP);
*(uint8_t*)arg = sock_pack_info[sn];
break;
default:
return SOCKERR_SOCKOPT;
}
return SOCK_OK;
}

View File

@ -1,472 +0,0 @@
//*****************************************************************************
//
//! \file socket.h
//! \brief SOCKET APIs Header file.
//! \details SOCKET APIs like as berkeley socket api.
//! \version 1.0.2
//! \date 2013/10/21
//! \par Revision history
//! <2014/05/01> V1.0.2. Refer to M20140501
//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED
//! 2. Add the comment as zero byte udp data reception in getsockopt().
//! <2013/10/21> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
/**
* @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs
* @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface.
* But there is a little bit of difference.
* @details
* <b> Comparison between WIZnet and Berkeley SOCKET APIs </b>
* <table>
* <tr> <td><b>API</b></td> <td><b>WIZnet</b></td> <td><b>Berkeley</b></td> </tr>
* <tr> <td>socket()</td> <td>O</td> <td>O</td> </tr>
* <tr> <td><b>bind()</b></td> <td>X</td> <td>O</td> </tr>
* <tr> <td><b>listen()</b></td> <td>O</td> <td>O</td> </tr>
* <tr> <td><b>connect()</b></td> <td>O</td> <td>O</td> </tr>
* <tr> <td><b>accept()</b></td> <td>X</td> <td>O</td> </tr>
* <tr> <td><b>recv()</b></td> <td>O</td> <td>O</td> </tr>
* <tr> <td><b>send()</b></td> <td>O</td> <td>O</td> </tr>
* <tr> <td><b>recvfrom()</b></td> <td>O</td> <td>O</td> </tr>
* <tr> <td><b>sendto()</b></td> <td>O</td> <td>O</td> </tr>
* <tr> <td><b>closesocket()</b></td> <td>O<br>close() & disconnect()</td> <td>O</td> </tr>
* </table>
* There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but,
* not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number,
* and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n
* When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port.
* When the listen SOCKET accepts a connection request from a client, it keeps listening.
* After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n
* Following figure shows network flow diagram by Berkeley SOCKET API.
* @image html Berkeley_SOCKET.jpg "<Berkeley SOCKET API>"
* But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n
* Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client,
* it is changed in order to communicate with the client.
* And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n
* If there're many listen SOCKET with same listen port number and a client requests a connection,
* the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n
* Following figure shows network flow diagram by WIZnet SOCKET API.
* @image html WIZnet_SOCKET.jpg "<WIZnet SOCKET API>"
*/
#ifndef _WIZCHIP_SOCKET_H_
#define _WIZCHIP_SOCKET_H_
// use this macro for exported names to avoid name clashes
#define WIZCHIP_EXPORT(name) wizchip_ ## name
#include "wizchip_conf.h"
#define SOCKET uint8_t ///< SOCKET type define for legacy driver
#define SOCK_OK 1 ///< Result is OK about socket process.
#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode.
#define SOCK_FATAL -1000 ///< Result is fatal error about socket process.
#define SOCK_ERROR 0
#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number
#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option
#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized
#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed.
#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation.
#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag
#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation.
#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument.
#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero
#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address
#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred
#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size.
#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication.
#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error.
/*
* SOCKET FLAG
*/
#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet
#define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2.
#define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack.
#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode.
#if _WIZCHIP_ == 5500
#define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500
#define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500
#define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500
#define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500
#endif
#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket().
/*
* UDP & MACRAW Packet Infomation
*/
#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet.
#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received.
#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet.
// resets all global state associated with the socket interface
void WIZCHIP_EXPORT(socket_reset)(void);
/**
* @ingroup WIZnet_socket_APIs
* @brief Open a socket.
* @details Initializes the socket with 'sn' passed as parameter and open.
*
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @param protocol Protocol type to operate such as TCP, UDP and MACRAW.
* @param port Port number to be bined.
* @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n
* Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK.
* @sa Sn_MR
*
* @return @b Success : The socket number @b 'sn' passed as parameter\n
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
* @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n
* @ref SOCKERR_SOCKFLAG - Invaild socket flag.
*/
int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);
/**
* @ingroup WIZnet_socket_APIs
* @brief Close a socket.
* @details It closes the socket with @b'sn' passed as parameter.
*
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
*
* @return @b Success : @ref SOCK_OK \n
* @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number
*/
int8_t WIZCHIP_EXPORT(close)(uint8_t sn);
/**
* @ingroup WIZnet_socket_APIs
* @brief Listen to a connection request from a client.
* @details It is listening to a connection request from a client.
* If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode.
*
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @return @b Success : @ref SOCK_OK \n
* @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n
* @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly.
*/
int8_t WIZCHIP_EXPORT(listen)(uint8_t sn);
/**
* @ingroup WIZnet_socket_APIs
* @brief Try to connect a server.
* @details It requests connection to the server with destination IP address and port number passed as parameter.\n
* @note It is valid only in TCP client mode.
* In block io mode, it does not return until connection is completed.
* In Non-block io mode, it return @ref SOCK_BUSY immediately.
*
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
* @param port Destination port number.
*
* @return @b Success : @ref SOCK_OK \n
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
* @ref SOCKERR_SOCKMODE - Invalid socket mode\n
* @ref SOCKERR_SOCKINIT - Socket is not initialized\n
* @ref SOCKERR_IPINVALID - Wrong server IP address\n
* @ref SOCKERR_PORTZERO - Server port zero\n
* @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n
* @ref SOCK_BUSY - In non-block io mode, it returned immediately\n
*/
int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port);
/**
* @ingroup WIZnet_socket_APIs
* @brief Try to disconnect a connection socket.
* @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client.
* @note It is valid only in TCP server or client mode. \n
* In block io mode, it does not return until disconnection is completed. \n
* In Non-block io mode, it return @ref SOCK_BUSY immediately. \n
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @return @b Success : @ref SOCK_OK \n
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
* @ref SOCK_BUSY - Socket is busy.
*/
int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn);
/**
* @ingroup WIZnet_socket_APIs
* @brief Send data to the connected peer in TCP socket.
* @details It is used to send outgoing data to the connected socket.
* @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n
* In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n
* In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @param buf Pointer buffer containing data to be sent.
* @param len The byte length of data in buf.
* @return @b Success : The sent data size \n
* @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
* @ref SOCKERR_DATALEN - zero data length \n
* @ref SOCK_BUSY - Socket is busy.
*/
int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len);
/**
* @ingroup WIZnet_socket_APIs
* @brief Receive data from the connected peer.
* @details It is used to read incoming data from the connected socket.\n
* It waits for data as much as the application wants to receive.
* @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n
* In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer. \n
* In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. \n
*
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @param buf Pointer buffer to read incoming data.
* @param len The max data length of data in buf.
* @return @b Success : The real received data size \n
* @b Fail :\n
* @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
* @ref SOCKERR_DATALEN - zero data length \n
* @ref SOCK_BUSY - Socket is busy.
*/
int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len);
/**
* @ingroup WIZnet_socket_APIs
* @brief Sends datagram to the peer with destination IP address and port number passed as parameter.
* @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n
* Even if the connectionless socket has been previously connected to a specific address,
* the address and port number parameters override the destination address for that particular datagram only.
* @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than <I>len</I>.
* In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough.
*
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @param buf Pointer buffer to send outgoing data.
* @param len The byte length of data in buf.
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
* @param port Destination port number.
*
* @return @b Success : The sent data size \n
* @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
* @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
* @ref SOCKERR_DATALEN - zero data length \n
* @ref SOCKERR_IPINVALID - Wrong server IP address\n
* @ref SOCKERR_PORTZERO - Server port zero\n
* @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
* @ref SOCK_BUSY - Socket is busy.
*/
int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
/**
* @ingroup WIZnet_socket_APIs
* @brief Receive datagram of UDP or MACRAW
* @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n
* This function is used to receive UDP and MAC_RAW mode, and handle the header as well.
* This function can divide to received the packet data.
* On the MACRAW SOCKET, the addr and port parameters are ignored.
* @note In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer
* In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer.
*
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @param buf Pointer buffer to read incoming data.
* @param len The max data length of data in buf.
* When the received packet size <= len, receives data as packet sized.
* When others, receives data as len.
* @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
* It is valid only when the first call recvfrom for receiving the packet.
* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
* @param port Pointer variable of destination port number.
* It is valid only when the first call recvform for receiving the packet.
* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
*
* @return @b Success : This function return real received data size for success.\n
* @b Fail : @ref SOCKERR_DATALEN - zero data length \n
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
* @ref SOCKBUSY - Socket is busy.
*/
int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
/////////////////////////////
// SOCKET CONTROL & OPTION //
/////////////////////////////
#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt().
#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt().
/**
* @defgroup DATA_TYPE DATA TYPE
*/
/**
* @ingroup DATA_TYPE
* @brief The kind of Socket Interrupt.
* @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR()
*/
typedef enum
{
SIK_CONNECTED = (1 << 0), ///< connected
SIK_DISCONNECTED = (1 << 1), ///< disconnected
SIK_RECEIVED = (1 << 2), ///< data received
SIK_TIMEOUT = (1 << 3), ///< timeout occurred
SIK_SENT = (1 << 4), ///< send ok
SIK_ALL = 0x1F, ///< all interrupt
}sockint_kind;
/**
* @ingroup DATA_TYPE
* @brief The type of @ref ctlsocket().
*/
typedef enum
{
CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK
CS_GET_IOMODE, ///< get socket IO mode
CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory
CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory
CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind
CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind
CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind
CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind
}ctlsock_type;
/**
* @ingroup DATA_TYPE
* @brief The type of socket option in @ref setsockopt() or @ref getsockopt()
*/
typedef enum
{
SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to <I>flag</I> in @ref socket().
SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() )
SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() )
SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() )
SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() )
SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() )
#if _WIZCHIP_ != 5100
SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode
#if _WIZCHIP_ > 5200
SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode
#endif
#endif
SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR()
SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR()
SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR()
SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode.
SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode.
}sockopt_type;
/**
* @ingroup WIZnet_socket_APIs
* @brief Control socket.
* @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information.
* Refer to @ref ctlsock_type.
* @param sn socket number
* @param cstype type of control socket. refer to @ref ctlsock_type.
* @param arg Data type and value is determined according to @ref ctlsock_type. \n
* <table>
* <tr> <td> @b cstype </td> <td> @b data type</td><td>@b value</td></tr>
* <tr> <td> @ref CS_SET_IOMODE \n @ref CS_GET_IOMODE </td> <td> uint8_t </td><td>@ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK</td></tr>
* <tr> <td> @ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF </td> <td> uint16_t </td><td> 0 ~ 16K </td></tr>
* <tr> <td> @ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK </td> <td> @ref sockint_kind </td><td> @ref SIK_CONNECTED, etc. </td></tr>
* </table>
* @return @b Success @ref SOCK_OK \n
* @b fail @ref SOCKERR_ARG - Invalid argument\n
*/
int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg);
/**
* @ingroup WIZnet_socket_APIs
* @brief set socket options
* @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type.
*
* @param sn socket number
* @param sotype socket option type. refer to @ref sockopt_type
* @param arg Data type and value is determined according to <I>sotype</I>. \n
* <table>
* <tr> <td> @b sotype </td> <td> @b data type</td><td>@b value</td></tr>
* <tr> <td> @ref SO_TTL </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
* <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
* <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr>
* <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr>
* <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
* <tr> <td> @ref SO_KEEPALIVESEND </td> <td> null </td><td> null </td></tr>
* <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr>
* </table>
* @return
* - @b Success : @ref SOCK_OK \n
* - @b Fail
* - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
* - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
* - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
* - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n
*/
int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg);
/**
* @ingroup WIZnet_socket_APIs
* @brief get socket options
* @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type
* @param sn socket number
* @param sotype socket option type. refer to @ref sockopt_type
* @param arg Data type and value is determined according to <I>sotype</I>. \n
* <table>
* <tr> <td> @b sotype </td> <td>@b data type</td><td>@b value</td></tr>
* <tr> <td> @ref SO_FLAG </td> <td> uint8_t </td><td> @ref SF_ETHER_OWN, etc... </td> </tr>
* <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
* <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr>
* <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr>
* <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> </td></tr>
* <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr>
* <tr> <td> @ref SO_SENDBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
* <tr> <td> @ref SO_RECVBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>
* <tr> <td> @ref SO_STATUS </td> <td> uint8_t </td><td> @ref SOCK_ESTABLISHED, etc.. </td></tr>
* <tr> <td> @ref SO_REMAINSIZE </td> <td> uint16_t </td><td> 0~ 65535 </td></tr>
* <tr> <td> @ref SO_PACKINFO </td> <td> uint8_t </td><td> @ref PACK_FIRST, etc... </td></tr>
* </table>
* @return
* - @b Success : @ref SOCK_OK \n
* - @b Fail
* - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
* - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
* - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
* @note
* The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n
* When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero,
* This means the zero byte UDP data(UDP Header only) received.
*/
int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg);
#endif // _WIZCHIP_SOCKET_H_

View File

@ -1,206 +0,0 @@
// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200
//*****************************************************************************
//
//! \file w5500.c
//! \brief W5500 HAL Interface.
//! \version 1.0.1
//! \date 2013/10/21
//! \par Revision history
//! <2014/05/01> V1.0.2
//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
//! Fixed the problem on porting into under 32bit MCU
//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
//! Thank for your interesting and serious advices.
//! <2013/10/21> 1st Release
//! <2013/12/20> V1.0.1
//! 1. Remove warning
//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
//! for loop optimized(removed). refer to M20131220
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
#include "w5200.h"
#define SMASK (0x7ff) /* tx buffer mask */
#define RMASK (0x7ff) /* rx buffer mask */
#define SSIZE (2048) /* max tx buffer size */
#define RSIZE (2048) /* max rx buffer size */
#define TXBUF_BASE (0x8000)
#define RXBUF_BASE (0xc000)
#define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */
#define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */
uint8_t WIZCHIP_READ(uint32_t AddrSel) {
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
uint8_t spi_data[4] = {
AddrSel >> 8,
AddrSel,
0x00,
0x01,
};
WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
uint8_t ret;
WIZCHIP.IF.SPI._read_bytes(&ret, 1);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
return ret;
}
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) {
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
uint8_t spi_data[5] = {
AddrSel >> 8,
AddrSel,
0x80,
0x01,
wb,
};
WIZCHIP.IF.SPI._write_bytes(spi_data, 5);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
uint8_t spi_data[4] = {
AddrSel >> 8,
AddrSel,
0x00 | ((len >> 8) & 0x7f),
len & 0xff,
};
WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
WIZCHIP.IF.SPI._read_bytes(pBuf, len);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
uint8_t spi_data[4] = {
AddrSel >> 8,
AddrSel,
0x80 | ((len >> 8) & 0x7f),
len & 0xff,
};
WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
WIZCHIP.IF.SPI._write_bytes(pBuf, len);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
uint16_t getSn_TX_FSR(uint8_t sn) {
uint16_t val = 0, val1 = 0;
do {
val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1);
if (val1 != 0) {
val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1);
}
} while (val != val1);
return val;
}
uint16_t getSn_RX_RSR(uint8_t sn) {
uint16_t val = 0, val1 = 0;
do {
val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1);
if (val1 != 0) {
val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1);
}
} while (val != val1);
return val;
}
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
if (len == 0) {
return;
}
uint16_t ptr = getSn_TX_WR(sn);
uint16_t offset = ptr & SMASK;
uint32_t addr = offset + SBASE(sn);
if (offset + len > SSIZE) {
// implement wrap-around circular buffer
uint16_t size = SSIZE - offset;
WIZCHIP_WRITE_BUF(addr, wizdata, size);
WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size);
} else {
WIZCHIP_WRITE_BUF(addr, wizdata, len);
}
ptr += len;
setSn_TX_WR(sn, ptr);
}
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
if (len == 0) {
return;
}
uint16_t ptr = getSn_RX_RD(sn);
uint16_t offset = ptr & RMASK;
uint16_t addr = RBASE(sn) + offset;
if (offset + len > RSIZE) {
// implement wrap-around circular buffer
uint16_t size = RSIZE - offset;
WIZCHIP_READ_BUF(addr, wizdata, size);
WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size);
} else {
WIZCHIP_READ_BUF(addr, wizdata, len);
}
ptr += len;
setSn_RX_RD(sn, ptr);
}
void wiz_recv_ignore(uint8_t sn, uint16_t len) {
uint16_t ptr = getSn_RX_RD(sn);
ptr += len;
setSn_RX_RD(sn, ptr);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,246 +0,0 @@
//*****************************************************************************
//
//! \file w5500.c
//! \brief W5500 HAL Interface.
//! \version 1.0.1
//! \date 2013/10/21
//! \par Revision history
//! <2014/05/01> V1.0.2
//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
//! Fixed the problem on porting into under 32bit MCU
//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
//! Thank for your interesting and serious advices.
//! <2013/10/21> 1st Release
//! <2013/12/20> V1.0.1
//! 1. Remove warning
//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
//! for loop optimized(removed). refer to M20131220
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
//#include <stdio.h>
#include "w5500.h"
#define _W5500_SPI_VDM_OP_ 0x00
#define _W5500_SPI_FDM_OP_LEN1_ 0x01
#define _W5500_SPI_FDM_OP_LEN2_ 0x02
#define _W5500_SPI_FDM_OP_LEN4_ 0x03
////////////////////////////////////////////////////
#define LPC_SSP0 (0)
static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) {
WIZCHIP.IF.SPI._read_bytes(buf, len);
}
static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) {
WIZCHIP.IF.SPI._write_bytes(buf, len);
}
uint8_t WIZCHIP_READ(uint32_t AddrSel)
{
uint8_t ret;
uint8_t spi_data[3];
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
//ret = WIZCHIP.IF.SPI._read_byte();
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
return ret;
}
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
{
uint8_t spi_data[4];
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
//WIZCHIP.IF.SPI._write_byte(wb);
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
spi_data[3] = wb;
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
{
uint8_t spi_data[3];
//uint16_t i;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
//for(i = 0; i < len; i++)
// pBuf[i] = WIZCHIP.IF.SPI._read_byte();
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
{
uint8_t spi_data[3];
//uint16_t i;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
//WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
//for(i = 0; i < len; i++)
// WIZCHIP.IF.SPI._write_byte(pBuf[i]);
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len);
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
uint16_t getSn_TX_FSR(uint8_t sn)
{
uint16_t val=0,val1=0;
do
{
val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
if (val1 != 0)
{
val = WIZCHIP_READ(Sn_TX_FSR(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
}
}while (val != val1);
return val;
}
uint16_t getSn_RX_RSR(uint8_t sn)
{
uint16_t val=0,val1=0;
do
{
val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
if (val1 != 0)
{
val = WIZCHIP_READ(Sn_RX_RSR(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
}
}while (val != val1);
return val;
}
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
{
uint16_t ptr = 0;
uint32_t addrsel = 0;
if(len == 0) return;
ptr = getSn_TX_WR(sn);
//M20140501 : implict type casting -> explict type casting
//addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
//
WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
ptr += len;
setSn_TX_WR(sn,ptr);
}
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
{
uint16_t ptr = 0;
uint32_t addrsel = 0;
if(len == 0) return;
ptr = getSn_RX_RD(sn);
//M20140501 : implict type casting -> explict type casting
//addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
//
WIZCHIP_READ_BUF(addrsel, wizdata, len);
ptr += len;
setSn_RX_RD(sn,ptr);
}
void wiz_recv_ignore(uint8_t sn, uint16_t len)
{
uint16_t ptr = 0;
ptr = getSn_RX_RD(sn);
ptr += len;
setSn_RX_RD(sn,ptr);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,662 +0,0 @@
//****************************************************************************/
//!
//! \file wizchip_conf.c
//! \brief WIZCHIP Config Header File.
//! \version 1.0.1
//! \date 2013/10/21
//! \par Revision history
//! <2014/05/01> V1.0.1 Refer to M20140501
//! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte()
// Issued by Mathias ClauBen.
//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t*
//! For remove the warning when pointer type size is not 32bit.
//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type.
//! <2013/10/21> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************/
//A20140501 : for use the type - ptrdiff_t
#include <stddef.h>
//
#include "wizchip_conf.h"
#include "socket.h"
/**
* @brief Default function to enable interrupt.
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
* null function is called.
*/
void wizchip_cris_enter(void) {};
/**
* @brief Default function to disable interrupt.
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
* null function is called.
*/
void wizchip_cris_exit(void) {};
/**
* @brief Default function to select chip.
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
* null function is called.
*/
void wizchip_cs_select(void) {};
/**
* @brief Default function to deselect chip.
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
* null function is called.
*/
void wizchip_cs_deselect(void) {};
/**
* @brief Default function to read in direct or indirect interface.
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
* null function is called.
*/
//M20140501 : Explict pointer type casting
//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); };
uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); };
/**
* @brief Default function to write in direct or indirect interface.
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
* null function is called.
*/
//M20140501 : Explict pointer type casting
//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; };
void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; };
/**
* @brief Default function to read in SPI interface.
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
* null function is called.
*/
void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {}
/**
* @brief Default function to write in SPI interface.
* @note This function help not to access wrong address. If you do not describe this function or register any functions,
* null function is called.
*/
void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {}
/**
* @\ref _WIZCHIP instance
*/
_WIZCHIP WIZCHIP =
{
.id = _WIZCHIP_ID_,
.if_mode = _WIZCHIP_IO_MODE_,
.CRIS._enter = wizchip_cris_enter,
.CRIS._exit = wizchip_cris_exit,
.CS._select = wizchip_cs_select,
.CS._deselect = wizchip_cs_deselect,
.IF.BUS._read_byte = wizchip_bus_readbyte,
.IF.BUS._write_byte = wizchip_bus_writebyte
// .IF.SPI._read_byte = wizchip_spi_readbyte,
// .IF.SPI._write_byte = wizchip_spi_writebyte
};
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
static uint8_t _SUBN_[4]; // subnet
#endif
static uint8_t _DNS_[4]; // DNS server ip address
static dhcp_mode _DHCP_; // DHCP mode
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void))
{
if(!cris_en || !cris_ex)
{
WIZCHIP.CRIS._enter = wizchip_cris_enter;
WIZCHIP.CRIS._exit = wizchip_cris_exit;
}
else
{
WIZCHIP.CRIS._enter = cris_en;
WIZCHIP.CRIS._exit = cris_ex;
}
}
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
{
if(!cs_sel || !cs_desel)
{
WIZCHIP.CS._select = wizchip_cs_select;
WIZCHIP.CS._deselect = wizchip_cs_deselect;
}
else
{
WIZCHIP.CS._select = cs_sel;
WIZCHIP.CS._deselect = cs_desel;
}
}
void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb))
{
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_));
if(!bus_rb || !bus_wb)
{
WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte;
WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte;
}
else
{
WIZCHIP.IF.BUS._read_byte = bus_rb;
WIZCHIP.IF.BUS._write_byte = bus_wb;
}
}
void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t))
{
while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
if(!spi_rb || !spi_wb)
{
WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes;
WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes;
}
else
{
WIZCHIP.IF.SPI._read_bytes = spi_rb;
WIZCHIP.IF.SPI._write_bytes = spi_wb;
}
}
int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg)
{
uint8_t tmp = 0;
uint8_t* ptmp[2] = {0,0};
switch(cwtype)
{
case CW_RESET_WIZCHIP:
wizchip_sw_reset();
break;
case CW_INIT_WIZCHIP:
if(arg != 0)
{
ptmp[0] = (uint8_t*)arg;
ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
}
return wizchip_init(ptmp[0], ptmp[1]);
case CW_CLR_INTERRUPT:
wizchip_clrinterrupt(*((intr_kind*)arg));
break;
case CW_GET_INTERRUPT:
*((intr_kind*)arg) = wizchip_getinterrupt();
break;
case CW_SET_INTRMASK:
wizchip_setinterruptmask(*((intr_kind*)arg));
break;
case CW_GET_INTRMASK:
*((intr_kind*)arg) = wizchip_getinterruptmask();
break;
#if _WIZCHIP_ > 5100
case CW_SET_INTRTIME:
setINTLEVEL(*(uint16_t*)arg);
break;
case CW_GET_INTRTIME:
*(uint16_t*)arg = getINTLEVEL();
break;
#endif
case CW_GET_ID:
((uint8_t*)arg)[0] = WIZCHIP.id[0];
((uint8_t*)arg)[1] = WIZCHIP.id[1];
((uint8_t*)arg)[2] = WIZCHIP.id[2];
((uint8_t*)arg)[3] = WIZCHIP.id[3];
((uint8_t*)arg)[4] = WIZCHIP.id[4];
((uint8_t*)arg)[5] = 0;
break;
#if _WIZCHIP_ == 5500
case CW_RESET_PHY:
wizphy_reset();
break;
case CW_SET_PHYCONF:
wizphy_setphyconf((wiz_PhyConf*)arg);
break;
case CW_GET_PHYCONF:
wizphy_getphyconf((wiz_PhyConf*)arg);
break;
case CW_GET_PHYSTATUS:
break;
case CW_SET_PHYPOWMODE:
return wizphy_setphypmode(*(uint8_t*)arg);
#endif
case CW_GET_PHYPOWMODE:
tmp = wizphy_getphypmode();
if((int8_t)tmp == -1) return -1;
*(uint8_t*)arg = tmp;
break;
case CW_GET_PHYLINK:
tmp = wizphy_getphylink();
if((int8_t)tmp == -1) return -1;
*(uint8_t*)arg = tmp;
break;
default:
return -1;
}
return 0;
}
int8_t ctlnetwork(ctlnetwork_type cntype, void* arg)
{
switch(cntype)
{
case CN_SET_NETINFO:
wizchip_setnetinfo((wiz_NetInfo*)arg);
break;
case CN_GET_NETINFO:
wizchip_getnetinfo((wiz_NetInfo*)arg);
break;
case CN_SET_NETMODE:
return wizchip_setnetmode(*(netmode_type*)arg);
case CN_GET_NETMODE:
*(netmode_type*)arg = wizchip_getnetmode();
break;
case CN_SET_TIMEOUT:
wizchip_settimeout((wiz_NetTimeout*)arg);
break;
case CN_GET_TIMEOUT:
wizchip_gettimeout((wiz_NetTimeout*)arg);
break;
default:
return -1;
}
return 0;
}
void wizchip_sw_reset(void)
{
uint8_t gw[4], sn[4], sip[4];
uint8_t mac[6];
getSHAR(mac);
getGAR(gw); getSUBR(sn); getSIPR(sip);
setMR(MR_RST);
getMR(); // for delay
setSHAR(mac);
setGAR(gw);
setSUBR(sn);
setSIPR(sip);
}
int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
{
int8_t i;
int8_t tmp = 0;
wizchip_sw_reset();
if(txsize)
{
tmp = 0;
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
tmp += txsize[i];
if(tmp > 16) return -1;
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
setSn_TXBUF_SIZE(i, txsize[i]);
}
if(rxsize)
{
tmp = 0;
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
tmp += rxsize[i];
if(tmp > 16) return -1;
for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
setSn_RXBUF_SIZE(i, rxsize[i]);
}
WIZCHIP_EXPORT(socket_reset)();
return 0;
}
void wizchip_clrinterrupt(intr_kind intr)
{
uint8_t ir = (uint8_t)intr;
uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
#if _WIZCHIP_ < 5500
ir |= (1<<4); // IK_WOL
#endif
#if _WIZCHIP_ == 5200
ir |= (1 << 6);
#endif
#if _WIZCHIP_ < 5200
sir &= 0x0F;
#endif
#if _WIZCHIP_ == 5100
ir |= sir;
setIR(ir);
#else
setIR(ir);
setSIR(sir);
#endif
}
intr_kind wizchip_getinterrupt(void)
{
uint8_t ir = 0;
uint8_t sir = 0;
uint16_t ret = 0;
#if _WIZCHIP_ == 5100
ir = getIR();
sir = ir 0x0F;
#else
ir = getIR();
sir = getSIR();
#endif
#if _WIZCHIP_ < 5500
ir &= ~(1<<4); // IK_WOL
#endif
#if _WIZCHIP_ == 5200
ir &= ~(1 << 6);
#endif
ret = sir;
ret = (ret << 8) + ir;
return (intr_kind)ret;
}
void wizchip_setinterruptmask(intr_kind intr)
{
uint8_t imr = (uint8_t)intr;
uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
#if _WIZCHIP_ < 5500
imr &= ~(1<<4); // IK_WOL
#endif
#if _WIZCHIP_ == 5200
imr &= ~(1 << 6);
#endif
#if _WIZCHIP_ < 5200
simr &= 0x0F;
#endif
#if _WIZCHIP_ == 5100
imr |= simr;
setIMR(imr);
#else
setIMR(imr);
setSIMR(simr);
#endif
}
intr_kind wizchip_getinterruptmask(void)
{
uint8_t imr = 0;
uint8_t simr = 0;
uint16_t ret = 0;
#if _WIZCHIP_ == 5100
imr = getIMR();
simr = imr 0x0F;
#else
imr = getIMR();
simr = getSIMR();
#endif
#if _WIZCHIP_ < 5500
imr &= ~(1<<4); // IK_WOL
#endif
#if _WIZCHIP_ == 5200
imr &= ~(1 << 6); // IK_DEST_UNREACH
#endif
ret = simr;
ret = (ret << 8) + imr;
return (intr_kind)ret;
}
int8_t wizphy_getphylink(void)
{
int8_t tmp;
#if _WIZCHIP_ == 5200
if(getPHYSTATUS() & PHYSTATUS_LINK)
tmp = PHY_LINK_ON;
else
tmp = PHY_LINK_OFF;
#elif _WIZCHIP_ == 5500
if(getPHYCFGR() & PHYCFGR_LNK_ON)
tmp = PHY_LINK_ON;
else
tmp = PHY_LINK_OFF;
#else
tmp = -1;
#endif
return tmp;
}
#if _WIZCHIP_ > 5100
int8_t wizphy_getphypmode(void)
{
int8_t tmp = 0;
#if _WIZCHIP_ == 5200
if(getPHYSTATUS() & PHYSTATUS_POWERDOWN)
tmp = PHY_POWER_DOWN;
else
tmp = PHY_POWER_NORM;
#elif _WIZCHIP_ == 5500
if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN)
tmp = PHY_POWER_DOWN;
else
tmp = PHY_POWER_NORM;
#else
tmp = -1;
#endif
return tmp;
}
#endif
#if _WIZCHIP_ == 5500
void wizphy_reset(void)
{
uint8_t tmp = getPHYCFGR();
tmp &= PHYCFGR_RST;
setPHYCFGR(tmp);
tmp = getPHYCFGR();
tmp |= ~PHYCFGR_RST;
setPHYCFGR(tmp);
}
void wizphy_setphyconf(wiz_PhyConf* phyconf)
{
uint8_t tmp = 0;
if(phyconf->by == PHY_CONFBY_SW)
tmp |= PHYCFGR_OPMD;
else
tmp &= ~PHYCFGR_OPMD;
if(phyconf->mode == PHY_MODE_AUTONEGO)
tmp |= PHYCFGR_OPMDC_ALLA;
else
{
if(phyconf->duplex == PHY_DUPLEX_FULL)
{
if(phyconf->speed == PHY_SPEED_100)
tmp |= PHYCFGR_OPMDC_100F;
else
tmp |= PHYCFGR_OPMDC_10F;
}
else
{
if(phyconf->speed == PHY_SPEED_100)
tmp |= PHYCFGR_OPMDC_100H;
else
tmp |= PHYCFGR_OPMDC_10H;
}
}
setPHYCFGR(tmp);
wizphy_reset();
}
void wizphy_getphyconf(wiz_PhyConf* phyconf)
{
uint8_t tmp = 0;
tmp = getPHYCFGR();
phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
switch(tmp & PHYCFGR_OPMDC_ALLA)
{
case PHYCFGR_OPMDC_ALLA:
case PHYCFGR_OPMDC_100FA:
phyconf->mode = PHY_MODE_AUTONEGO;
break;
default:
phyconf->mode = PHY_MODE_MANUAL;
break;
}
switch(tmp & PHYCFGR_OPMDC_ALLA)
{
case PHYCFGR_OPMDC_100FA:
case PHYCFGR_OPMDC_100F:
case PHYCFGR_OPMDC_100H:
phyconf->speed = PHY_SPEED_100;
break;
default:
phyconf->speed = PHY_SPEED_10;
break;
}
switch(tmp & PHYCFGR_OPMDC_ALLA)
{
case PHYCFGR_OPMDC_100FA:
case PHYCFGR_OPMDC_100F:
case PHYCFGR_OPMDC_10F:
phyconf->duplex = PHY_DUPLEX_FULL;
break;
default:
phyconf->duplex = PHY_DUPLEX_HALF;
break;
}
}
void wizphy_getphystat(wiz_PhyConf* phyconf)
{
uint8_t tmp = getPHYCFGR();
phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
}
int8_t wizphy_setphypmode(uint8_t pmode)
{
uint8_t tmp = 0;
tmp = getPHYCFGR();
if((tmp & PHYCFGR_OPMD)== 0) return -1;
tmp &= ~PHYCFGR_OPMDC_ALLA;
if( pmode == PHY_POWER_DOWN)
tmp |= PHYCFGR_OPMDC_PDOWN;
else
tmp |= PHYCFGR_OPMDC_ALLA;
setPHYCFGR(tmp);
wizphy_reset();
tmp = getPHYCFGR();
if( pmode == PHY_POWER_DOWN)
{
if(tmp & PHYCFGR_OPMDC_PDOWN) return 0;
}
else
{
if(tmp & PHYCFGR_OPMDC_ALLA) return 0;
}
return -1;
}
#endif
void wizchip_setnetinfo(wiz_NetInfo* pnetinfo)
{
setSHAR(pnetinfo->mac);
setGAR(pnetinfo->gw);
setSUBR(pnetinfo->sn);
setSIPR(pnetinfo->ip);
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
_SUBN_[0] = pnetinfo->sn[0];
_SUBN_[1] = pnetinfo->sn[1];
_SUBN_[2] = pnetinfo->sn[2];
_SUBN_[3] = pnetinfo->sn[3];
#endif
_DNS_[0] = pnetinfo->dns[0];
_DNS_[1] = pnetinfo->dns[1];
_DNS_[2] = pnetinfo->dns[2];
_DNS_[3] = pnetinfo->dns[3];
_DHCP_ = pnetinfo->dhcp;
}
void wizchip_getnetinfo(wiz_NetInfo* pnetinfo)
{
getSHAR(pnetinfo->mac);
getGAR(pnetinfo->gw);
getSUBR(pnetinfo->sn);
getSIPR(pnetinfo->ip);
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
pnetinfo->sn[0] = _SUBN_[0];
pnetinfo->sn[1] = _SUBN_[1];
pnetinfo->sn[2] = _SUBN_[2];
pnetinfo->sn[3] = _SUBN_[3];
#endif
pnetinfo->dns[0]= _DNS_[0];
pnetinfo->dns[1]= _DNS_[1];
pnetinfo->dns[2]= _DNS_[2];
pnetinfo->dns[3]= _DNS_[3];
pnetinfo->dhcp = _DHCP_;
}
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
uint8_t *wizchip_getsubn(void) {
return _SUBN_;
}
#endif
int8_t wizchip_setnetmode(netmode_type netmode)
{
uint8_t tmp = 0;
#if _WIZCHIP_ != 5500
if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1;
#else
if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1;
#endif
tmp = getMR();
tmp |= (uint8_t)netmode;
setMR(tmp);
return 0;
}
netmode_type wizchip_getnetmode(void)
{
return (netmode_type) getMR();
}
void wizchip_settimeout(wiz_NetTimeout* nettime)
{
setRCR(nettime->retry_cnt);
setRTR(nettime->time_100us);
}
void wizchip_gettimeout(wiz_NetTimeout* nettime)
{
nettime->retry_cnt = getRCR();
nettime->time_100us = getRTR();
}

View File

@ -1,554 +0,0 @@
//*****************************************************************************
//
//! \file wizchip_conf.h
//! \brief WIZCHIP Config Header File.
//! \version 1.0.0
//! \date 2013/10/21
//! \par Revision history
//! <2013/10/21> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
/**
* @defgroup extra_functions 2. WIZnet Extra Functions
*
* @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions.
* @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n
*
*/
#ifndef _WIZCHIP_CONF_H_
#define _WIZCHIP_CONF_H_
#include <stdint.h>
/**
* @brief Select WIZCHIP.
* @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n
* ex> <code> #define \_WIZCHIP_ 5500 </code>
*/
#ifndef _WIZCHIP_
#define _WIZCHIP_ 5200 // 5100, 5200, 5500
#endif
#define _WIZCHIP_IO_MODE_NONE_ 0x0000
#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */
#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */
//#define _WIZCHIP_IO_MODE_IIC_ 0x0400
//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800
// Add to
//
#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */
#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */
#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/
#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/
#if (_WIZCHIP_ == 5100)
#define _WIZCHIP_ID_ "W5100\0"
/**
* @brief Define interface mode.
* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
*/
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
#elif (_WIZCHIP_ == 5200)
#define _WIZCHIP_ID_ "W5200\0"
/**
* @brief Define interface mode.
* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
*/
// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
#include "w5200/w5200.h"
#elif (_WIZCHIP_ == 5500)
#define _WIZCHIP_ID_ "W5500\0"
/**
* @brief Define interface mode. \n
* @todo Should select interface mode as chip.
* - @ref \_WIZCHIP_IO_MODE_SPI_ \n
* -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n
* -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n
* - @ref \_WIZCHIP_IO_MODE_BUS_ \n
* - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n
* - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n
* - Others will be defined in future. \n\n
* ex> <code> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ </code>
*
*/
//#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_
#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_
#include "w5500/w5500.h"
#else
#error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!"
#endif
#ifndef _WIZCHIP_IO_MODE_
#error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!"
#endif
/**
* @brief Define I/O base address when BUS IF mode.
* @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_,
* @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n
* ex> <code> #define \_WIZCHIP_IO_BASE_ 0x00008000 </code>
*/
#define _WIZCHIP_IO_BASE_ 0x00000000 //
#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
#ifndef _WIZCHIP_IO_BASE_
#error "You should be define _WIZCHIP_IO_BASE to fit your system memory map."
#endif
#endif
#if _WIZCHIP_ > 5100
#define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP
#else
#define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP
#endif
/********************************************************
* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC.
*********************************************************/
/**
* @ingroup DATA_TYPE
* @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200
*/
typedef struct __WIZCHIP
{
uint16_t if_mode; ///< host interface mode
uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on.
/**
* The set of critical section callback func.
*/
struct _CRIS
{
void (*_enter) (void); ///< crtical section enter
void (*_exit) (void); ///< critial section exit
}CRIS;
/**
* The set of @ref\_WIZCHIP_ select control callback func.
*/
struct _CS
{
void (*_select) (void); ///< @ref \_WIZCHIP_ selected
void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected
}CS;
/**
* The set of interface IO callback func.
*/
union _IF
{
/**
* For BUS interface IO
*/
struct
{
uint8_t (*_read_byte) (uint32_t AddrSel);
void (*_write_byte) (uint32_t AddrSel, uint8_t wb);
}BUS;
/**
* For SPI interface IO
*/
struct
{
void (*_read_bytes) (uint8_t *buf, uint32_t len);
void (*_write_bytes) (const uint8_t *buf, uint32_t len);
}SPI;
// To be added
//
}IF;
}_WIZCHIP;
extern _WIZCHIP WIZCHIP;
/**
* @ingroup DATA_TYPE
* WIZCHIP control type enumration used in @ref ctlwizchip().
*/
typedef enum
{
CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly
CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t.
CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP
CW_CLR_INTERRUPT, ///< Clears interrupt
CW_SET_INTRMASK, ///< Masks interrupt
CW_GET_INTRMASK, ///< Get interrupt mask
CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt.
CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt.
CW_GET_ID, ///< Gets WIZCHIP name.
#if _WIZCHIP_ == 5500
CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000
CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000
CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000
CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000
CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000
#endif
CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal
CW_GET_PHYLINK ///< Get PHY Link status
}ctlwizchip_type;
/**
* @ingroup DATA_TYPE
* Network control type enumration used in @ref ctlnetwork().
*/
typedef enum
{
CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo
CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo
CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode
CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode
CN_SET_TIMEOUT, ///< Set network timeout as retry count and time.
CN_GET_TIMEOUT, ///< Get network timeout as retry count and time.
}ctlnetwork_type;
/**
* @ingroup DATA_TYPE
* Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK
* and CW_GET_INTRMASK is used in @ref ctlnetwork().
* It can be used with OR operation.
*/
typedef enum
{
#if _WIZCHIP_ > 5200
IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500.
#endif
IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected
#if _WIZCHIP_ != 5200
IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200
#endif
IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred
IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt
IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt
IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt
IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt
#if _WIZCHIP_ > 5100
IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100
IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100
IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100
IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100
#endif
#if _WIZCHIP_ > 5100
IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt
#else
IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt
#endif
}intr_kind;
#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin
#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register
#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting.
#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation
#define PHY_SPEED_10 0 ///< Link Speed 10
#define PHY_SPEED_100 1 ///< Link Speed 100
#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex
#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex
#define PHY_LINK_OFF 0 ///< Link Off
#define PHY_LINK_ON 1 ///< Link On
#define PHY_POWER_NORM 0 ///< PHY power normal mode
#define PHY_POWER_DOWN 1 ///< PHY power down mode
#if _WIZCHIP_ == 5500
/**
* @ingroup DATA_TYPE
* It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500,
* and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n
* Valid only in W5500.
*/
typedef struct wiz_PhyConf_t
{
uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW
uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO
uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100
uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL
//uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN
//uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF
}wiz_PhyConf;
#endif
/**
* @ingroup DATA_TYPE
* It used in setting dhcp_mode of @ref wiz_NetInfo.
*/
typedef enum
{
NETINFO_STATIC = 1, ///< Static IP configuration by manually.
NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever
}dhcp_mode;
/**
* @ingroup DATA_TYPE
* Network Information for WIZCHIP
*/
typedef struct wiz_NetInfo_t
{
uint8_t mac[6]; ///< Source Mac Address
uint8_t ip[4]; ///< Source IP Address
uint8_t sn[4]; ///< Subnet Mask
uint8_t gw[4]; ///< Gateway IP Address
uint8_t dns[4]; ///< DNS server IP Address
dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP
}wiz_NetInfo;
/**
* @ingroup DATA_TYPE
* Network mode
*/
typedef enum
{
#if _WIZCHIP_ == 5500
NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500
#endif
NM_WAKEONLAN = (1<<5), ///< Wake On Lan
NM_PINGBLOCK = (1<<4), ///< Block ping-request
NM_PPPOE = (1<<3), ///< PPPoE mode
}netmode_type;
/**
* @ingroup DATA_TYPE
* Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation.
*/
typedef struct wiz_NetTimeout_t
{
uint8_t retry_cnt; ///< retry count
uint16_t time_100us; ///< time unit 100us
}wiz_NetTimeout;
/**
*@brief Registers call back function for critical section of I/O functions such as
*\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF.
*@param cris_en : callback function for critical section enter.
*@param cris_ex : callback function for critical section exit.
*@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions.
*@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called.
*/
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));
/**
*@brief Registers call back function for WIZCHIP select & deselect.
*@param cs_sel : callback function for WIZCHIP select
*@param cs_desel : callback fucntion for WIZCHIP deselect
*@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions.
*@note If you do not describe or register, null function is called.
*/
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));
/**
*@brief Registers call back function for bus interface.
*@param bus_rb : callback function to read byte data using system bus
*@param bus_wb : callback function to write byte data using system bus
*@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function
*or register your functions.
*@note If you do not describe or register, null function is called.
*/
void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb));
/**
*@brief Registers call back function for SPI interface.
*@param spi_rb : callback function to read byte usig SPI
*@param spi_wb : callback function to write byte usig SPI
*@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function
*or register your functions.
*@note If you do not describe or register, null function is called.
*/
void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t));
/**
* @ingroup extra_functions
* @brief Controls to the WIZCHIP.
* @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto),
* controls interrupt & mask and so on.
* @param cwtype : Decides to the control type
* @param arg : arg type is dependent on cwtype.
* @return 0 : Success \n
* -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP
*/
int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg);
/**
* @ingroup extra_functions
* @brief Controls to network.
* @details Controls to network environment, mode, timeout and so on.
* @param cntype : Input. Decides to the control type
* @param arg : Inout. arg type is dependent on cntype.
* @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n
* 0 : Success
*/
int8_t ctlnetwork(ctlnetwork_type cntype, void* arg);
/*
* The following functions are implemented for internal use.
* but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork().
*/
/**
* @ingroup extra_functions
* @brief Reset WIZCHIP by softly.
*/
void wizchip_sw_reset(void);
/**
* @ingroup extra_functions
* @brief Initializes WIZCHIP with socket buffer size
* @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB.
* @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB.
* @return 0 : succcess \n
* -1 : fail. Invalid buffer size
*/
int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize);
/**
* @ingroup extra_functions
* @brief Clear Interrupt of WIZCHIP.
* @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
*/
void wizchip_clrinterrupt(intr_kind intr);
/**
* @ingroup extra_functions
* @brief Get Interrupt of WIZCHIP.
* @return @ref intr_kind value operated OR. It can type-cast to uint16_t.
*/
intr_kind wizchip_getinterrupt(void);
/**
* @ingroup extra_functions
* @brief Mask or Unmask Interrupt of WIZCHIP.
* @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
*/
void wizchip_setinterruptmask(intr_kind intr);
/**
* @ingroup extra_functions
* @brief Get Interrupt mask of WIZCHIP.
* @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t.
*/
intr_kind wizchip_getinterruptmask(void);
#if _WIZCHIP_ > 5100
int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100
int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100
#endif
#if _WIZCHIP_ == 5500
void wizphy_reset(void); ///< Reset phy. Vailid only in W5500
/**
* @ingroup extra_functions
* @brief Set the phy information for WIZCHIP without power mode
* @param phyconf : @ref wiz_PhyConf
*/
void wizphy_setphyconf(wiz_PhyConf* phyconf);
/**
* @ingroup extra_functions
* @brief Get phy configuration information.
* @param phyconf : @ref wiz_PhyConf
*/
void wizphy_getphyconf(wiz_PhyConf* phyconf);
/**
* @ingroup extra_functions
* @brief Get phy status.
* @param phyconf : @ref wiz_PhyConf
*/
void wizphy_getphystat(wiz_PhyConf* phyconf);
/**
* @ingroup extra_functions
* @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200
* @param pmode Settig value of power down mode.
*/
int8_t wizphy_setphypmode(uint8_t pmode);
#endif
/**
* @ingroup extra_functions
* @brief Set the network information for WIZCHIP
* @param pnetinfo : @ref wizNetInfo
*/
void wizchip_setnetinfo(wiz_NetInfo* pnetinfo);
/**
* @ingroup extra_functions
* @brief Get the network information for WIZCHIP
* @param pnetinfo : @ref wizNetInfo
*/
void wizchip_getnetinfo(wiz_NetInfo* pnetinfo);
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
uint8_t *wizchip_getsubn(void);
#endif
/**
* @ingroup extra_functions
* @brief Set the network mode such WOL, PPPoE, Ping Block, and etc.
* @param pnetinfo Value of network mode. Refer to @ref netmode_type.
*/
int8_t wizchip_setnetmode(netmode_type netmode);
/**
* @ingroup extra_functions
* @brief Get the network mode such WOL, PPPoE, Ping Block, and etc.
* @return Value of network mode. Refer to @ref netmode_type.
*/
netmode_type wizchip_getnetmode(void);
/**
* @ingroup extra_functions
* @brief Set retry time value(@ref RTR) and retry count(@ref RCR).
* @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission.
* @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout.
*/
void wizchip_settimeout(wiz_NetTimeout* nettime);
/**
* @ingroup extra_functions
* @brief Get retry time value(@ref RTR) and retry count(@ref RCR).
* @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission.
* @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout.
*/
void wizchip_gettimeout(wiz_NetTimeout* nettime);
#endif // _WIZCHIP_CONF_H_

View File

@ -1,975 +0,0 @@
//*****************************************************************************
//
//! \file dhcp.c
//! \brief DHCP APIs implement file.
//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
//! \version 1.1.0
//! \date 2013/11/18
//! \par Revision history
//! <2018/10/09> Modified by Nick Moore for CircuitPython
//! <2013/11/18> 1st Release
//! <2012/12/20> V1.1.0
//! 1. Optimize code
//! 2. Add reg_dhcp_cbfunc()
//! 3. Add DHCP_stop()
//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run()
//! 5. Don't care system endian
//! 6. Add comments
//! <2012/12/26> V1.1.1
//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization
//! \author Eric Jung & MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
//#include "Ethernet/socket.h"
//#include "Internet/DHCP/dhcp.h"
#include "../../ethernet/socket.h"
#include "dhcp.h"
/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
#ifdef _DHCP_DEBUG_
#include <stdio.h>
#endif
/* DHCP state machine. */
#define STATE_DHCP_INIT 0 ///< Initialize
#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER
#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK
#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased
#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP
#define STATE_DHCP_RELEASE 5 ///< No use
#define STATE_DHCP_STOP 6 ///< Stop processing DHCP
#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG
#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG
/* DHCP message OP code */
#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG
#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG
/* DHCP message type */
#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG
#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG
#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG
#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG
#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG
#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG
#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use
#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use
#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG
#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG
#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG
#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG
#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG
#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time
#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG
#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG
/*
* @brief DHCP option and value (cf. RFC1533)
*/
enum
{
padOption = 0,
subnetMask = 1,
timerOffset = 2,
routersOnSubnet = 3,
timeServer = 4,
nameServer = 5,
dns = 6,
logServer = 7,
cookieServer = 8,
lprServer = 9,
impressServer = 10,
resourceLocationServer = 11,
hostName = 12,
bootFileSize = 13,
meritDumpFile = 14,
domainName = 15,
swapServer = 16,
rootPath = 17,
extentionsPath = 18,
IPforwarding = 19,
nonLocalSourceRouting = 20,
policyFilter = 21,
maxDgramReasmSize = 22,
defaultIPTTL = 23,
pathMTUagingTimeout = 24,
pathMTUplateauTable = 25,
ifMTU = 26,
allSubnetsLocal = 27,
broadcastAddr = 28,
performMaskDiscovery = 29,
maskSupplier = 30,
performRouterDiscovery = 31,
routerSolicitationAddr = 32,
staticRoute = 33,
trailerEncapsulation = 34,
arpCacheTimeout = 35,
ethernetEncapsulation = 36,
tcpDefaultTTL = 37,
tcpKeepaliveInterval = 38,
tcpKeepaliveGarbage = 39,
nisDomainName = 40,
nisServers = 41,
ntpServers = 42,
vendorSpecificInfo = 43,
netBIOSnameServer = 44,
netBIOSdgramDistServer = 45,
netBIOSnodeType = 46,
netBIOSscope = 47,
xFontServer = 48,
xDisplayManager = 49,
dhcpRequestedIPaddr = 50,
dhcpIPaddrLeaseTime = 51,
dhcpOptionOverload = 52,
dhcpMessageType = 53,
dhcpServerIdentifier = 54,
dhcpParamRequest = 55,
dhcpMsg = 56,
dhcpMaxMsgSize = 57,
dhcpT1value = 58,
dhcpT2value = 59,
dhcpClassIdentifier = 60,
dhcpClientIdentifier = 61,
endOption = 255
};
/*
* @brief DHCP message format
*/
typedef struct {
uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY
uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB
uint8_t hlen; ///< @ref DHCP_HLENETHERNET
uint8_t hops; ///< @ref DHCP_HOPS
uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction.
uint16_t secs; ///< @ref DHCP_SECS
uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST
uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever
uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server
uint8_t siaddr[4]; ///< No use
uint8_t giaddr[4]; ///< No use
uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero
uint8_t sname[64]; ///< No use
uint8_t file[128]; ///< No use
uint8_t OPT[OPT_SIZE]; ///< Option
} RIP_MSG;
uint8_t DHCP_SOCKET; // Socket number for DHCP
uint8_t DHCP_SIP[4]; // DHCP Server IP address
// Network information from DHCP Server
uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address
uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP
uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP
uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP
uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP
int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state
int8_t dhcp_retry_count = 0;
uint32_t dhcp_lease_time = INFINITE_LEASETIME;
volatile uint32_t dhcp_tick_1s = 0; // unit 1 second
uint32_t dhcp_tick_next = DHCP_WAIT_TIME ;
uint32_t DHCP_XID; // Any number
RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing
uint8_t HOST_NAME[] = DCHP_HOST_NAME;
uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address.
/* The default callback function */
void default_ip_assign(void);
void default_ip_update(void);
void default_ip_conflict(void);
/* Callback handler */
void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */
void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */
void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */
void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
/* send DISCOVER message to DHCP server */
void send_DHCP_DISCOVER(void);
/* send REQEUST message to DHCP server */
void send_DHCP_REQUEST(void);
/* send DECLINE message to DHCP server */
void send_DHCP_DECLINE(void);
/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */
int8_t check_DHCP_leasedIP(void);
/* check the timeout in DHCP process */
uint8_t check_DHCP_timeout(void);
/* Intialize to timeout process. */
void reset_DHCP_timeout(void);
/* Parse message as OFFER and ACK and NACK from DHCP server.*/
int8_t parseDHCPCMSG(void);
/* The default handler of ip assign first */
void default_ip_assign(void)
{
setSIPR(DHCP_allocated_ip);
setSUBR(DHCP_allocated_sn);
setGAR (DHCP_allocated_gw);
}
/* The default handler of ip changed */
void default_ip_update(void)
{
/* WIZchip Software Reset */
setMR(MR_RST);
getMR(); // for delay
default_ip_assign();
setSHAR(DHCP_CHADDR);
}
/* The default handler of ip changed */
void default_ip_conflict(void)
{
// WIZchip Software Reset
setMR(MR_RST);
getMR(); // for delay
setSHAR(DHCP_CHADDR);
}
/* register the call back func. */
void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void))
{
dhcp_ip_assign = default_ip_assign;
dhcp_ip_update = default_ip_update;
dhcp_ip_conflict = default_ip_conflict;
if(ip_assign) dhcp_ip_assign = ip_assign;
if(ip_update) dhcp_ip_update = ip_update;
if(ip_conflict) dhcp_ip_conflict = ip_conflict;
}
/* make the common DHCP message */
void makeDHCPMSG(void)
{
uint8_t bk_mac[6];
uint8_t* ptmp;
uint8_t i;
getSHAR(bk_mac);
pDHCPMSG->op = DHCP_BOOTREQUEST;
pDHCPMSG->htype = DHCP_HTYPE10MB;
pDHCPMSG->hlen = DHCP_HLENETHERNET;
pDHCPMSG->hops = DHCP_HOPS;
ptmp = (uint8_t*)(&pDHCPMSG->xid);
*(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
*(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
*(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
*(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
pDHCPMSG->secs = DHCP_SECS;
ptmp = (uint8_t*)(&pDHCPMSG->flags);
*(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
*(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
pDHCPMSG->ciaddr[0] = 0;
pDHCPMSG->ciaddr[1] = 0;
pDHCPMSG->ciaddr[2] = 0;
pDHCPMSG->ciaddr[3] = 0;
pDHCPMSG->yiaddr[0] = 0;
pDHCPMSG->yiaddr[1] = 0;
pDHCPMSG->yiaddr[2] = 0;
pDHCPMSG->yiaddr[3] = 0;
pDHCPMSG->siaddr[0] = 0;
pDHCPMSG->siaddr[1] = 0;
pDHCPMSG->siaddr[2] = 0;
pDHCPMSG->siaddr[3] = 0;
pDHCPMSG->giaddr[0] = 0;
pDHCPMSG->giaddr[1] = 0;
pDHCPMSG->giaddr[2] = 0;
pDHCPMSG->giaddr[3] = 0;
pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0;
for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0;
for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;
// MAGIC_COOKIE
pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0;
}
/* SEND DHCP DISCOVER */
void send_DHCP_DISCOVER(void)
{
uint16_t i;
uint8_t ip[4];
uint16_t k = 0;
makeDHCPMSG();
k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
// Option Request Param
pDHCPMSG->OPT[k++] = dhcpMessageType;
pDHCPMSG->OPT[k++] = 0x01;
pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
// Client identifier
pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
pDHCPMSG->OPT[k++] = 0x07;
pDHCPMSG->OPT[k++] = 0x01;
pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
// host name
pDHCPMSG->OPT[k++] = hostName;
pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname
for(i = 0 ; HOST_NAME[i] != 0; i++)
pDHCPMSG->OPT[k++] = HOST_NAME[i];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
pDHCPMSG->OPT[k++] = dhcpParamRequest;
pDHCPMSG->OPT[k++] = 0x06; // length of request
pDHCPMSG->OPT[k++] = subnetMask;
pDHCPMSG->OPT[k++] = routersOnSubnet;
pDHCPMSG->OPT[k++] = dns;
pDHCPMSG->OPT[k++] = domainName;
pDHCPMSG->OPT[k++] = dhcpT1value;
pDHCPMSG->OPT[k++] = dhcpT2value;
pDHCPMSG->OPT[k++] = endOption;
for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
// send broadcasting packet
ip[0] = 255;
ip[1] = 255;
ip[2] = 255;
ip[3] = 255;
#ifdef _DHCP_DEBUG_
printf("> Send DHCP_DISCOVER\r\n");
#endif
WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
}
/* SEND DHCP REQUEST */
void send_DHCP_REQUEST(void)
{
int i;
uint8_t ip[4];
uint16_t k = 0;
makeDHCPMSG();
if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST)
{
*((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
*((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
ip[0] = DHCP_SIP[0];
ip[1] = DHCP_SIP[1];
ip[2] = DHCP_SIP[2];
ip[3] = DHCP_SIP[3];
}
else
{
ip[0] = 255;
ip[1] = 255;
ip[2] = 255;
ip[3] = 255;
}
k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
// Option Request Param.
pDHCPMSG->OPT[k++] = dhcpMessageType;
pDHCPMSG->OPT[k++] = 0x01;
pDHCPMSG->OPT[k++] = DHCP_REQUEST;
pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
pDHCPMSG->OPT[k++] = 0x07;
pDHCPMSG->OPT[k++] = 0x01;
pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
{
pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
pDHCPMSG->OPT[k++] = 0x04;
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
pDHCPMSG->OPT[k++] = 0x04;
pDHCPMSG->OPT[k++] = DHCP_SIP[0];
pDHCPMSG->OPT[k++] = DHCP_SIP[1];
pDHCPMSG->OPT[k++] = DHCP_SIP[2];
pDHCPMSG->OPT[k++] = DHCP_SIP[3];
}
// host name
pDHCPMSG->OPT[k++] = hostName;
pDHCPMSG->OPT[k++] = 0; // length of hostname
for(i = 0 ; HOST_NAME[i] != 0; i++)
pDHCPMSG->OPT[k++] = HOST_NAME[i];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
pDHCPMSG->OPT[k++] = dhcpParamRequest;
pDHCPMSG->OPT[k++] = 0x08;
pDHCPMSG->OPT[k++] = subnetMask;
pDHCPMSG->OPT[k++] = routersOnSubnet;
pDHCPMSG->OPT[k++] = dns;
pDHCPMSG->OPT[k++] = domainName;
pDHCPMSG->OPT[k++] = dhcpT1value;
pDHCPMSG->OPT[k++] = dhcpT2value;
pDHCPMSG->OPT[k++] = performRouterDiscovery;
pDHCPMSG->OPT[k++] = staticRoute;
pDHCPMSG->OPT[k++] = endOption;
for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
#ifdef _DHCP_DEBUG_
printf("> Send DHCP_REQUEST\r\n");
#endif
WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
}
/* SEND DHCP DHCPDECLINE */
void send_DHCP_DECLINE(void)
{
int i;
uint8_t ip[4];
uint16_t k = 0;
makeDHCPMSG();
k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
*((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
*((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
// Option Request Param.
pDHCPMSG->OPT[k++] = dhcpMessageType;
pDHCPMSG->OPT[k++] = 0x01;
pDHCPMSG->OPT[k++] = DHCP_DECLINE;
pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
pDHCPMSG->OPT[k++] = 0x07;
pDHCPMSG->OPT[k++] = 0x01;
pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
pDHCPMSG->OPT[k++] = 0x04;
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
pDHCPMSG->OPT[k++] = 0x04;
pDHCPMSG->OPT[k++] = DHCP_SIP[0];
pDHCPMSG->OPT[k++] = DHCP_SIP[1];
pDHCPMSG->OPT[k++] = DHCP_SIP[2];
pDHCPMSG->OPT[k++] = DHCP_SIP[3];
pDHCPMSG->OPT[k++] = endOption;
for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
//send broadcasting packet
ip[0] = 0xFF;
ip[1] = 0xFF;
ip[2] = 0xFF;
ip[3] = 0xFF;
#ifdef _DHCP_DEBUG_
printf("\r\n> Send DHCP_DECLINE\r\n");
#endif
WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
}
/* PARSE REPLY pDHCPMSG */
int8_t parseDHCPMSG(void)
{
uint8_t svr_addr[6];
uint16_t svr_port;
uint16_t len;
uint8_t * p;
uint8_t * e;
uint8_t type = 0;
uint8_t opt_len;
if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0)
{
len = WIZCHIP_EXPORT(recvfrom)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port);
#ifdef _DHCP_DEBUG_
printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len);
#endif
}
else return 0;
if (svr_port == DHCP_SERVER_PORT) {
// compare mac address
if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
(pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
(pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) )
return 0;
type = 0;
p = (uint8_t *)(&pDHCPMSG->op);
p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
e = p + (len - 240);
while ( p < e ) {
switch ( *p ) {
case endOption :
p = e; // for break while(p < e)
break;
case padOption :
p++;
break;
case dhcpMessageType :
p++;
p++;
type = *p++;
break;
case subnetMask :
p++;
p++;
DHCP_allocated_sn[0] = *p++;
DHCP_allocated_sn[1] = *p++;
DHCP_allocated_sn[2] = *p++;
DHCP_allocated_sn[3] = *p++;
break;
case routersOnSubnet :
p++;
opt_len = *p++;
DHCP_allocated_gw[0] = *p++;
DHCP_allocated_gw[1] = *p++;
DHCP_allocated_gw[2] = *p++;
DHCP_allocated_gw[3] = *p++;
p = p + (opt_len - 4);
break;
case dns :
p++;
opt_len = *p++;
DHCP_allocated_dns[0] = *p++;
DHCP_allocated_dns[1] = *p++;
DHCP_allocated_dns[2] = *p++;
DHCP_allocated_dns[3] = *p++;
p = p + (opt_len - 4);
break;
case dhcpIPaddrLeaseTime :
p++;
opt_len = *p++;
dhcp_lease_time = *p++;
dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
#ifdef _DHCP_DEBUG_
dhcp_lease_time = 10;
#endif
break;
case dhcpServerIdentifier :
p++;
opt_len = *p++;
DHCP_SIP[0] = *p++;
DHCP_SIP[1] = *p++;
DHCP_SIP[2] = *p++;
DHCP_SIP[3] = *p++;
break;
default :
p++;
opt_len = *p++;
p += opt_len;
break;
} // switch
} // while
} // if
return type;
}
uint8_t DHCP_run(void)
{
uint8_t type;
uint8_t ret;
if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED;
if(getSn_SR(DHCP_SOCKET) != SOCK_UDP)
WIZCHIP_EXPORT(socket)(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
ret = DHCP_RUNNING;
type = parseDHCPMSG();
switch ( dhcp_state ) {
case STATE_DHCP_INIT :
DHCP_allocated_ip[0] = 0;
DHCP_allocated_ip[1] = 0;
DHCP_allocated_ip[2] = 0;
DHCP_allocated_ip[3] = 0;
send_DHCP_DISCOVER();
dhcp_state = STATE_DHCP_DISCOVER;
break;
case STATE_DHCP_DISCOVER :
if (type == DHCP_OFFER){
#ifdef _DHCP_DEBUG_
printf("> Receive DHCP_OFFER\r\n");
#endif
DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
send_DHCP_REQUEST();
dhcp_state = STATE_DHCP_REQUEST;
} else ret = check_DHCP_timeout();
break;
case STATE_DHCP_REQUEST :
if (type == DHCP_ACK) {
#ifdef _DHCP_DEBUG_
printf("> Receive DHCP_ACK\r\n");
#endif
if (check_DHCP_leasedIP()) {
// Network info assignment from DHCP
dhcp_ip_assign();
reset_DHCP_timeout();
dhcp_state = STATE_DHCP_LEASED;
} else {
// IP address conflict occurred
reset_DHCP_timeout();
dhcp_ip_conflict();
dhcp_state = STATE_DHCP_INIT;
}
} else if (type == DHCP_NAK) {
#ifdef _DHCP_DEBUG_
printf("> Receive DHCP_NACK\r\n");
#endif
reset_DHCP_timeout();
dhcp_state = STATE_DHCP_DISCOVER;
} else ret = check_DHCP_timeout();
break;
case STATE_DHCP_LEASED :
ret = DHCP_IP_LEASED;
if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) {
#ifdef _DHCP_DEBUG_
printf("> Maintains the IP address \r\n");
#endif
type = 0;
OLD_allocated_ip[0] = DHCP_allocated_ip[0];
OLD_allocated_ip[1] = DHCP_allocated_ip[1];
OLD_allocated_ip[2] = DHCP_allocated_ip[2];
OLD_allocated_ip[3] = DHCP_allocated_ip[3];
DHCP_XID++;
send_DHCP_REQUEST();
reset_DHCP_timeout();
dhcp_state = STATE_DHCP_REREQUEST;
}
break;
case STATE_DHCP_REREQUEST :
ret = DHCP_IP_LEASED;
if (type == DHCP_ACK) {
dhcp_retry_count = 0;
if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
OLD_allocated_ip[3] != DHCP_allocated_ip[3])
{
ret = DHCP_IP_CHANGED;
dhcp_ip_update();
#ifdef _DHCP_DEBUG_
printf(">IP changed.\r\n");
#endif
}
#ifdef _DHCP_DEBUG_
else printf(">IP is continued.\r\n");
#endif
reset_DHCP_timeout();
dhcp_state = STATE_DHCP_LEASED;
} else if (type == DHCP_NAK) {
#ifdef _DHCP_DEBUG_
printf("> Receive DHCP_NACK, Failed to maintain ip\r\n");
#endif
reset_DHCP_timeout();
dhcp_state = STATE_DHCP_DISCOVER;
} else ret = check_DHCP_timeout();
break;
default :
break;
}
return ret;
}
void DHCP_stop(void)
{
WIZCHIP_EXPORT(close)(DHCP_SOCKET);
dhcp_state = STATE_DHCP_STOP;
}
uint8_t check_DHCP_timeout(void)
{
uint8_t ret = DHCP_RUNNING;
if (dhcp_retry_count < MAX_DHCP_RETRY) {
if (dhcp_tick_next < dhcp_tick_1s) {
switch ( dhcp_state ) {
case STATE_DHCP_DISCOVER :
// printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n");
send_DHCP_DISCOVER();
break;
case STATE_DHCP_REQUEST :
// printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n");
send_DHCP_REQUEST();
break;
case STATE_DHCP_REREQUEST :
// printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n");
send_DHCP_REQUEST();
break;
default :
break;
}
dhcp_tick_1s = 0;
dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
dhcp_retry_count++;
}
} else { // timeout occurred
switch(dhcp_state) {
case STATE_DHCP_DISCOVER:
dhcp_state = STATE_DHCP_INIT;
ret = DHCP_FAILED;
break;
case STATE_DHCP_REQUEST:
case STATE_DHCP_REREQUEST:
send_DHCP_DISCOVER();
dhcp_state = STATE_DHCP_DISCOVER;
break;
default :
break;
}
reset_DHCP_timeout();
}
return ret;
}
int8_t check_DHCP_leasedIP(void)
{
uint8_t tmp;
int32_t ret;
//WIZchip RCR value changed for ARP Timeout count control
tmp = getRCR();
setRCR(0x03);
// IP conflict detection : ARP request - ARP reply
// Broadcasting ARP Request for check the IP conflict using UDP sendto() function
ret = WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
// RCR value restore
setRCR(tmp);
if(ret == SOCKERR_TIMEOUT) {
// UDP send Timeout occurred : allocated IP address is unique, DHCP Success
#ifdef _DHCP_DEBUG_
printf("\r\n> Check leased IP - OK\r\n");
#endif
return 1;
} else {
// Received ARP reply or etc : IP address conflict occur, DHCP Failed
send_DHCP_DECLINE();
ret = dhcp_tick_1s;
while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message;
return 0;
}
}
void DHCP_init(uint8_t s, DHCP_INIT_BUFFER_TYPE* buf)
{
uint8_t zeroip[4] = {0,0,0,0};
getSHAR(DHCP_CHADDR);
if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
{
// assign temporary mac address, you should be set SHAR before call this function.
DHCP_CHADDR[0] = 0x00;
DHCP_CHADDR[1] = 0x08;
DHCP_CHADDR[2] = 0xdc;
DHCP_CHADDR[3] = 0x00;
DHCP_CHADDR[4] = 0x00;
DHCP_CHADDR[5] = 0x00;
setSHAR(DHCP_CHADDR);
}
DHCP_SOCKET = s; // SOCK_DHCP
pDHCPMSG = (RIP_MSG*)buf;
DHCP_XID = 0x12345678;
// WIZchip Netinfo Clear
setSIPR(zeroip);
setSIPR(zeroip);
setGAR(zeroip);
reset_DHCP_timeout();
dhcp_state = STATE_DHCP_INIT;
}
/* Rset the DHCP timeout count and retry count. */
void reset_DHCP_timeout(void)
{
dhcp_tick_1s = 0;
dhcp_tick_next = DHCP_WAIT_TIME;
dhcp_retry_count = 0;
}
void DHCP_time_handler(void)
{
dhcp_tick_1s++;
}
void getIPfromDHCP(uint8_t* ip)
{
ip[0] = DHCP_allocated_ip[0];
ip[1] = DHCP_allocated_ip[1];
ip[2] = DHCP_allocated_ip[2];
ip[3] = DHCP_allocated_ip[3];
}
void getGWfromDHCP(uint8_t* ip)
{
ip[0] =DHCP_allocated_gw[0];
ip[1] =DHCP_allocated_gw[1];
ip[2] =DHCP_allocated_gw[2];
ip[3] =DHCP_allocated_gw[3];
}
void getSNfromDHCP(uint8_t* ip)
{
ip[0] = DHCP_allocated_sn[0];
ip[1] = DHCP_allocated_sn[1];
ip[2] = DHCP_allocated_sn[2];
ip[3] = DHCP_allocated_sn[3];
}
void getDNSfromDHCP(uint8_t* ip)
{
ip[0] = DHCP_allocated_dns[0];
ip[1] = DHCP_allocated_dns[1];
ip[2] = DHCP_allocated_dns[2];
ip[3] = DHCP_allocated_dns[3];
}
uint32_t getDHCPLeasetime(void)
{
return dhcp_lease_time;
}

View File

@ -1,152 +0,0 @@
//*****************************************************************************
//
//! \file dhcp.h
//! \brief DHCP APIs Header file.
//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
//! \version 1.1.0
//! \date 2013/11/18
//! \par Revision history
//! <2013/11/18> 1st Release
//! <2012/12/20> V1.1.0
//! 1. Move unreferenced DEFINE to dhcp.c
//! <2012/12/26> V1.1.1
//! \author Eric Jung & MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
#ifndef _DHCP_H_
#define _DHCP_H_
/*
* @brief
* @details If you want to display debug & processing message, Define _DHCP_DEBUG_
* @note If defined, it depends on <stdio.h>
*/
//#define _DHCP_DEBUG_
/* Retry to processing DHCP */
#define MAX_DHCP_RETRY 2 ///< Maximum retry count
#define DHCP_WAIT_TIME 3 ///< Wait Time 3s (was 10s)
/* UDP port numbers for DHCP */
#define DHCP_SERVER_PORT 67 ///< DHCP server port number
#define DHCP_CLIENT_PORT 68 ///< DHCP client port number
#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number
#define DCHP_HOST_NAME "WIZnet\0"
/*
* @brief return value of @ref DHCP_run()
*/
enum
{
DHCP_FAILED = 0, ///< Processing Fail
DHCP_RUNNING, ///< Processing DHCP protocol
DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign)
DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update)
DHCP_IP_LEASED, ///< Stand by
DHCP_STOPPED ///< Stop processing DHCP protocol
};
#define DHCP_INIT_BUFFER_TYPE uint32_t
#define DHCP_INIT_BUFFER_SIZE (137)
/*
* @brief DHCP client initialization (outside of the main loop)
* @param s - socket number
* @param buf - buffer for processing DHCP message
*/
void DHCP_init(uint8_t s, DHCP_INIT_BUFFER_TYPE* buf);
/*
* @brief DHCP 1s Tick Timer handler
* @note SHOULD BE register to your system 1s Tick timer handler
*/
void DHCP_time_handler(void);
/*
* @brief Register call back function
* @param ip_assign - callback func when IP is assigned from DHCP server first
* @param ip_update - callback func when IP is changed
* @prarm ip_conflict - callback func when the assigned IP is conflict with others.
*/
void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
/*
* @brief DHCP client in the main loop
* @return The value is as the follow \n
* @ref DHCP_FAILED \n
* @ref DHCP_RUNNING \n
* @ref DHCP_IP_ASSIGN \n
* @ref DHCP_IP_CHANGED \n
* @ref DHCP_IP_LEASED \n
* @ref DHCP_STOPPED \n
*
* @note This function is always called by you main task.
*/
uint8_t DHCP_run(void);
/*
* @brief Stop DHCP processing
* @note If you want to restart. call DHCP_init() and DHCP_run()
*/
void DHCP_stop(void);
/* Get Network information assigned from DHCP server */
/*
* @brief Get IP address
* @param ip - IP address to be returned
*/
void getIPfromDHCP(uint8_t* ip);
/*
* @brief Get Gateway address
* @param ip - Gateway address to be returned
*/
void getGWfromDHCP(uint8_t* ip);
/*
* @brief Get Subnet mask value
* @param ip - Subnet mask to be returned
*/
void getSNfromDHCP(uint8_t* ip);
/*
* @brief Get DNS address
* @param ip - DNS address to be returned
*/
void getDNSfromDHCP(uint8_t* ip);
/*
* @brief Get the leased time by DHCP sever
* @return unit 1s
*/
uint32_t getDHCPLeasetime(void);
#endif /* _DHCP_H_ */

View File

@ -1,572 +0,0 @@
//*****************************************************************************
//
//! \file dns.c
//! \brief DNS APIs Implement file.
//! \details Send DNS query & Receive DNS reponse. \n
//! It depends on stdlib.h & string.h in ansi-c library
//! \version 1.1.0
//! \date 2013/11/18
//! \par Revision history
//! <2013/10/21> 1st Release
//! <2013/12/20> V1.1.0
//! 1. Remove secondary DNS server in DNS_run
//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
//! 2. DNS_timerHandler -> DNS_time_handler
//! 3. Remove the unused define
//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
//! <2013/12/20> V1.1.0
//! <2018/10/04> Modified HAL_GetTick for use with CircuitPython by Nick Moore
//!
//! \author Eric Jung & MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
#include <string.h>
#include <stdlib.h>
#include "supervisor/shared/tick.h"
//#include "Ethernet/socket.h"
//#include "Internet/DNS/dns.h"
#include "../../ethernet/socket.h"
#include "dns.h"
#ifdef _DNS_DEBUG_
#include <stdio.h>
#endif
#define INITRTT 2000L /* Initial smoothed response time */
#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */
#define TYPE_A 1 /* Host address */
#define TYPE_NS 2 /* Name server */
#define TYPE_MD 3 /* Mail destination (obsolete) */
#define TYPE_MF 4 /* Mail forwarder (obsolete) */
#define TYPE_CNAME 5 /* Canonical name */
#define TYPE_SOA 6 /* Start of Authority */
#define TYPE_MB 7 /* Mailbox name (experimental) */
#define TYPE_MG 8 /* Mail group member (experimental) */
#define TYPE_MR 9 /* Mail rename name (experimental) */
#define TYPE_NULL 10 /* Null (experimental) */
#define TYPE_WKS 11 /* Well-known sockets */
#define TYPE_PTR 12 /* Pointer record */
#define TYPE_HINFO 13 /* Host information */
#define TYPE_MINFO 14 /* Mailbox information (experimental)*/
#define TYPE_MX 15 /* Mail exchanger */
#define TYPE_TXT 16 /* Text strings */
#define TYPE_ANY 255 /* Matches any type */
#define CLASS_IN 1 /* The ARPA Internet */
/* Round trip timing parameters */
#define AGAIN 8 /* Average RTT gain = 1/8 */
#define LAGAIN 3 /* Log2(AGAIN) */
#define DGAIN 4 /* Mean deviation gain = 1/4 */
#define LDGAIN 2 /* log2(DGAIN) */
/* Header for all domain messages */
struct dhdr
{
uint16_t id; /* Identification */
uint8_t qr; /* Query/Response */
#define QUERY 0
#define RESPONSE 1
uint8_t opcode;
#define IQUERY 1
uint8_t aa; /* Authoratative answer */
uint8_t tc; /* Truncation */
uint8_t rd; /* Recursion desired */
uint8_t ra; /* Recursion available */
uint8_t rcode; /* Response code */
#define NO_ERROR 0
#define FORMAT_ERROR 1
#define SERVER_FAIL 2
#define NAME_ERROR 3
#define NOT_IMPL 4
#define REFUSED 5
uint16_t qdcount; /* Question count */
uint16_t ancount; /* Answer count */
uint16_t nscount; /* Authority (name server) count */
uint16_t arcount; /* Additional record count */
};
uint8_t* pDNSMSG; // DNS message buffer
uint8_t DNS_SOCKET; // SOCKET number for DNS
uint16_t DNS_MSGID; // DNS message ID
uint32_t HAL_GetTick(void) {
return supervisor_ticks_ms32();
}
uint32_t hal_sys_tick;
/* converts uint16_t from network buffer to a host byte order integer. */
uint16_t get16(uint8_t * s)
{
uint16_t i;
i = *s++ << 8;
i = i + *s;
return i;
}
/* copies uint16_t to the network buffer with network byte order. */
uint8_t * put16(uint8_t * s, uint16_t i)
{
*s++ = i >> 8;
*s++ = i;
return s;
}
/*
* CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM
*
* Description : This function converts a compressed domain name to the human-readable form
* Arguments : msg - is a pointer to the reply message
* compressed - is a pointer to the domain name in reply message.
* buf - is a pointer to the buffer for the human-readable form name.
* len - is the MAX. size of buffer.
* Returns : the length of compressed message
*/
int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len)
{
uint16_t slen; /* Length of current segment */
uint8_t * cp;
int clen = 0; /* Total length of compressed name */
int indirect = 0; /* Set if indirection encountered */
int nseg = 0; /* Total number of segments in name */
cp = compressed;
for (;;)
{
slen = *cp++; /* Length of this segment */
if (!indirect) clen++;
if ((slen & 0xc0) == 0xc0)
{
if (!indirect)
clen++;
indirect = 1;
/* Follow indirection */
cp = &msg[((slen & 0x3f)<<8) + *cp];
slen = *cp++;
}
if (slen == 0) /* zero length == all done */
break;
len -= slen + 1;
if (len < 0) return -1;
if (!indirect) clen += slen;
while (slen-- != 0) *buf++ = (char)*cp++;
*buf++ = '.';
nseg++;
}
if (nseg == 0)
{
/* Root name; represent as single dot */
*buf++ = '.';
len--;
}
*buf++ = '\0';
len--;
return clen; /* Length of compressed message */
}
/*
* PARSE QUESTION SECTION
*
* Description : This function parses the question record of the reply message.
* Arguments : msg - is a pointer to the reply message
* cp - is a pointer to the question record.
* Returns : a pointer the to next record.
*/
uint8_t * dns_question(uint8_t * msg, uint8_t * cp)
{
int len;
char name[MAXCNAME];
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) return 0;
cp += len;
cp += 2; /* type */
cp += 2; /* class */
return cp;
}
/*
* PARSE ANSER SECTION
*
* Description : This function parses the answer record of the reply message.
* Arguments : msg - is a pointer to the reply message
* cp - is a pointer to the answer record.
* Returns : a pointer the to next record.
*/
uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns)
{
int len, type;
char name[MAXCNAME];
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) return 0;
cp += len;
type = get16(cp);
cp += 2; /* type */
cp += 2; /* class */
cp += 4; /* ttl */
cp += 2; /* len */
switch (type)
{
case TYPE_A:
/* Just read the address directly into the structure */
ip_from_dns[0] = *cp++;
ip_from_dns[1] = *cp++;
ip_from_dns[2] = *cp++;
ip_from_dns[3] = *cp++;
break;
case TYPE_CNAME:
case TYPE_MB:
case TYPE_MG:
case TYPE_MR:
case TYPE_NS:
case TYPE_PTR:
/* These types all consist of a single domain name */
/* convert it to ASCII format */
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) return 0;
cp += len;
break;
case TYPE_HINFO:
len = *cp++;
cp += len;
len = *cp++;
cp += len;
break;
case TYPE_MX:
cp += 2;
/* Get domain name of exchanger */
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) return 0;
cp += len;
break;
case TYPE_SOA:
/* Get domain name of name server */
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) return 0;
cp += len;
/* Get domain name of responsible person */
len = parse_name(msg, cp, name, MAXCNAME);
if (len == -1) return 0;
cp += len;
cp += 4;
cp += 4;
cp += 4;
cp += 4;
cp += 4;
break;
case TYPE_TXT:
/* Just stash */
break;
default:
/* Ignore */
break;
}
return cp;
}
/*
* PARSE THE DNS REPLY
*
* Description : This function parses the reply message from DNS server.
* Arguments : dhdr - is a pointer to the header for DNS message
* buf - is a pointer to the reply message.
* len - is the size of reply message.
* Returns : -1 - Domain name length is too big
* 0 - Fail (Timeout or parse error)
* 1 - Success,
*/
int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns)
{
uint16_t tmp;
uint16_t i;
uint8_t * msg;
uint8_t * cp;
msg = pbuf;
memset(pdhdr, 0, sizeof(*pdhdr));
pdhdr->id = get16(&msg[0]);
tmp = get16(&msg[2]);
if (tmp & 0x8000) pdhdr->qr = 1;
pdhdr->opcode = (tmp >> 11) & 0xf;
if (tmp & 0x0400) pdhdr->aa = 1;
if (tmp & 0x0200) pdhdr->tc = 1;
if (tmp & 0x0100) pdhdr->rd = 1;
if (tmp & 0x0080) pdhdr->ra = 1;
pdhdr->rcode = tmp & 0xf;
pdhdr->qdcount = get16(&msg[4]);
pdhdr->ancount = get16(&msg[6]);
pdhdr->nscount = get16(&msg[8]);
pdhdr->arcount = get16(&msg[10]);
/* Now parse the variable length sections */
cp = &msg[12];
/* Question section */
for (i = 0; i < pdhdr->qdcount; i++)
{
cp = dns_question(msg, cp);
if(!cp)
{
#ifdef _DNS_DEBUG_
printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n");
#endif
return -1;
}
}
/* Answer section */
for (i = 0; i < pdhdr->ancount; i++)
{
cp = dns_answer(msg, cp, ip_from_dns);
if(!cp)
{
#ifdef _DNS_DEBUG_
printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n");
#endif
return -1;
}
}
/* Name server (authority) section */
for (i = 0; i < pdhdr->nscount; i++)
{
;
}
/* Additional section */
for (i = 0; i < pdhdr->arcount; i++)
{
;
}
if(pdhdr->rcode == 0) return 1; // No error
else return 0;
}
/*
* MAKE DNS QUERY MESSAGE
*
* Description : This function makes DNS query message.
* Arguments : op - Recursion desired
* name - is a pointer to the domain name.
* buf - is a pointer to the buffer for DNS message.
* len - is the MAX. size of buffer.
* Returns : the pointer to the DNS message.
*/
int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len)
{
uint8_t *cp;
char *cp1;
char sname[MAXCNAME];
char *dname;
uint16_t p;
uint16_t dlen;
cp = buf;
DNS_MSGID++;
cp = put16(cp, DNS_MSGID);
p = (op << 11) | 0x0100; /* Recursion desired */
cp = put16(cp, p);
cp = put16(cp, 1);
cp = put16(cp, 0);
cp = put16(cp, 0);
cp = put16(cp, 0);
strcpy(sname, name);
dname = sname;
dlen = strlen(dname);
for (;;)
{
/* Look for next dot */
cp1 = strchr(dname, '.');
if (cp1 != NULL) len = cp1 - dname; /* More to come */
else len = dlen; /* Last component */
*cp++ = len; /* Write length of component */
if (len == 0) break;
/* Copy component up to (but not including) dot */
memcpy(cp, dname, len);
cp += len;
if (cp1 == NULL)
{
*cp++ = 0; /* Last one; write null and finish */
break;
}
dname += len+1;
dlen -= len+1;
}
cp = put16(cp, 0x0001); /* type */
cp = put16(cp, 0x0001); /* class */
return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf)));
}
/*
* CHECK DNS TIMEOUT
*
* Description : This function check the DNS timeout
* Arguments : None.
* Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur
* Note : timeout : retry count and timer both over.
*/
int8_t check_DNS_timeout(void)
{
static uint8_t retry_count;
uint32_t tick = HAL_GetTick();
if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000)
{
hal_sys_tick = tick;
if(retry_count >= MAX_DNS_RETRY) {
retry_count = 0;
return -1; // timeout occurred
}
retry_count++;
return 0; // timer over, but no timeout
}
return 1; // no timer over, no timeout occur
}
/* DNS CLIENT INIT */
void DNS_init(uint8_t s, uint8_t * buf)
{
DNS_SOCKET = s; // SOCK_DNS
pDNSMSG = buf; // User's shared buffer
DNS_MSGID = DNS_MSG_ID;
}
/* DNS CLIENT RUN */
int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns)
{
int8_t ret;
struct dhdr dhp;
uint8_t ip[4];
uint16_t len, port;
int8_t ret_check_timeout;
hal_sys_tick = HAL_GetTick();
// Socket open
WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0);
#ifdef _DNS_DEBUG_
printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
#endif
len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE);
WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
while (1)
{
if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0)
{
if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE;
len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port);
#ifdef _DNS_DEBUG_
printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len);
#endif
ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns);
break;
}
// Check Timeout
ret_check_timeout = check_DNS_timeout();
if (ret_check_timeout < 0) {
#ifdef _DNS_DEBUG_
printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
#endif
return 0; // timeout occurred
}
else if (ret_check_timeout == 0) {
#ifdef _DNS_DEBUG_
printf("> DNS Timeout\r\n");
#endif
WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
}
}
WIZCHIP_EXPORT(close)(DNS_SOCKET);
// Return value
// 0 > : failed / 1 - success
return ret;
}

View File

@ -1,96 +0,0 @@
//*****************************************************************************
//
//! \file dns.h
//! \brief DNS APIs Header file.
//! \details Send DNS query & Receive DNS reponse.
//! \version 1.1.0
//! \date 2013/11/18
//! \par Revision history
//! <2013/10/21> 1st Release
//! <2013/12/20> V1.1.0
//! 1. Remove secondary DNS server in DNS_run
//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
//! 2. DNS_timerHandler -> DNS_time_handler
//! 3. Move the no reference define to dns.c
//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
//! <2013/12/20> V1.1.0
//!
//! \author Eric Jung & MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
#ifndef _DNS_H_
#define _DNS_H_
#include <stdint.h>
/*
* @brief Define it for Debug & Monitor DNS processing.
* @note If defined, it depends on <stdio.h>
*/
//#define _DNS_DEBUG_
#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */
/*
* @brief Maximum length of your queried Domain name
* @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1)
* @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack.
*/
#define MAX_DOMAIN_NAME 32 // for example "www.google.com"
#define MAX_DNS_RETRY 2 ///< Requery Count
#define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s.
#define IPPORT_DOMAIN 53 ///< DNS server port number
#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number
/*
* @brief DNS process initialize
* @param s : Socket number for DNS
* @param buf : Buffer for DNS message
*/
void DNS_init(uint8_t s, uint8_t * buf);
/*
* @brief DNS process
* @details Send DNS query and receive DNS response
* @param dns_ip : DNS server ip address
* @param name : Domain name to be queried
* @param ip_from_dns : IP address from DNS server
* @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n
* 0 : failed (Timeout or Parse error)\n
* 1 : success
* @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME
*/
int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns);
#endif /* _DNS_H_ */

View File

@ -0,0 +1,117 @@
/*
* Automatically generated header file: don't edit
*/
#define HAVE_DOT_CONFIG 1
#define CONFIG_PLATFORM_LINUX 1
#undef CONFIG_PLATFORM_CYGWIN
#undef CONFIG_PLATFORM_WIN32
/*
* General Configuration
*/
#define PREFIX "/usr/local"
#undef CONFIG_DEBUG
#undef CONFIG_STRIP_UNWANTED_SECTIONS
#undef CONFIG_VISUAL_STUDIO_7_0
#undef CONFIG_VISUAL_STUDIO_8_0
#undef CONFIG_VISUAL_STUDIO_10_0
#define CONFIG_VISUAL_STUDIO_7_0_BASE ""
#define CONFIG_VISUAL_STUDIO_8_0_BASE ""
#define CONFIG_VISUAL_STUDIO_10_0_BASE ""
#define CONFIG_EXTRA_CFLAGS_OPTIONS ""
#define CONFIG_EXTRA_LDFLAGS_OPTIONS ""
/*
* SSL Library
*/
#undef CONFIG_SSL_SERVER_ONLY
#undef CONFIG_SSL_CERT_VERIFICATION
#undef CONFIG_SSL_FULL_MODE
#define CONFIG_SSL_SKELETON_MODE 1
#define CONFIG_SSL_ENABLE_SERVER 1
#define CONFIG_SSL_ENABLE_CLIENT 1
#undef CONFIG_SSL_DIAGNOSTICS
#define CONFIG_SSL_PROT_LOW 1
#undef CONFIG_SSL_PROT_MEDIUM
#undef CONFIG_SSL_PROT_HIGH
#define CONFIG_SSL_AES 1
#define CONFIG_SSL_USE_DEFAULT_KEY 1
#define CONFIG_SSL_PRIVATE_KEY_LOCATION ""
#define CONFIG_SSL_PRIVATE_KEY_PASSWORD ""
#define CONFIG_SSL_X509_CERT_LOCATION ""
#undef CONFIG_SSL_GENERATE_X509_CERT
#define CONFIG_SSL_X509_COMMON_NAME ""
#define CONFIG_SSL_X509_ORGANIZATION_NAME ""
#define CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME ""
#undef CONFIG_SSL_HAS_PEM
#undef CONFIG_SSL_USE_PKCS12
#define CONFIG_SSL_EXPIRY_TIME
#define CONFIG_X509_MAX_CA_CERTS 0
#define CONFIG_SSL_MAX_CERTS 3
#undef CONFIG_SSL_CTX_MUTEXING
#undef CONFIG_USE_DEV_URANDOM
#undef CONFIG_WIN32_USE_CRYPTO_LIB
#undef CONFIG_OPENSSL_COMPATIBLE
#undef CONFIG_PERFORMANCE_TESTING
#undef CONFIG_SSL_TEST
#undef CONFIG_AXTLSWRAP
#undef CONFIG_AXHTTPD
#undef CONFIG_HTTP_STATIC_BUILD
#define CONFIG_HTTP_PORT
#define CONFIG_HTTP_HTTPS_PORT
#define CONFIG_HTTP_SESSION_CACHE_SIZE
#define CONFIG_HTTP_WEBROOT ""
#define CONFIG_HTTP_TIMEOUT
#undef CONFIG_HTTP_HAS_CGI
#define CONFIG_HTTP_CGI_EXTENSIONS ""
#undef CONFIG_HTTP_ENABLE_LUA
#define CONFIG_HTTP_LUA_PREFIX ""
#undef CONFIG_HTTP_BUILD_LUA
#define CONFIG_HTTP_CGI_LAUNCHER ""
#undef CONFIG_HTTP_DIRECTORIES
#undef CONFIG_HTTP_HAS_AUTHORIZATION
#undef CONFIG_HTTP_HAS_IPV6
#undef CONFIG_HTTP_ENABLE_DIFFERENT_USER
#define CONFIG_HTTP_USER ""
#undef CONFIG_HTTP_VERBOSE
#undef CONFIG_HTTP_IS_DAEMON
/*
* Language Bindings
*/
#undef CONFIG_BINDINGS
#undef CONFIG_CSHARP_BINDINGS
#undef CONFIG_VBNET_BINDINGS
#define CONFIG_DOT_NET_FRAMEWORK_BASE ""
#undef CONFIG_JAVA_BINDINGS
#define CONFIG_JAVA_HOME ""
#undef CONFIG_PERL_BINDINGS
#define CONFIG_PERL_CORE ""
#define CONFIG_PERL_LIB ""
#undef CONFIG_LUA_BINDINGS
#define CONFIG_LUA_CORE ""
/*
* Samples
*/
#undef CONFIG_SAMPLES
#undef CONFIG_C_SAMPLES
#undef CONFIG_CSHARP_SAMPLES
#undef CONFIG_VBNET_SAMPLES
#undef CONFIG_JAVA_SAMPLES
#undef CONFIG_PERL_SAMPLES
#undef CONFIG_LUA_SAMPLES
#undef CONFIG_BIGINT_CLASSICAL
#undef CONFIG_BIGINT_MONTGOMERY
#undef CONFIG_BIGINT_BARRETT
#undef CONFIG_BIGINT_CRT
#undef CONFIG_BIGINT_KARATSUBA
#define MUL_KARATSUBA_THRESH
#define SQU_KARATSUBA_THRESH
#undef CONFIG_BIGINT_SLIDING_WINDOW
#undef CONFIG_BIGINT_SQUARE
#undef CONFIG_BIGINT_CHECK_ON
#undef CONFIG_INTEGER_32BIT
#undef CONFIG_INTEGER_16BIT
#undef CONFIG_INTEGER_8BIT

View File

@ -0,0 +1 @@
#define AXTLS_VERSION "(no version)"

View File

@ -1,94 +0,0 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
//
// SPDX-License-Identifier: MIT
#include "py/runtime.h"
#include "extmod/machine_mem.h"
#if MICROPY_PY_MACHINE
// If you wish to override the functions for mapping the machine_mem read/write
// address, then add a #define for MICROPY_MACHINE_MEM_GET_READ_ADDR and/or
// MICROPY_MACHINE_MEM_GET_WRITE_ADDR in your mpconfigport.h. Since the
// prototypes are identical, it is allowable for both of the macros to evaluate
// the to same function.
//
// It is expected that the modmachine.c file for a given port will provide the
// implementations, if the default implementation isn't used.
#if !defined(MICROPY_MACHINE_MEM_GET_READ_ADDR) || !defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
STATIC uintptr_t machine_mem_get_addr(mp_obj_t addr_o, uint align) {
uintptr_t addr = mp_obj_int_get_truncated(addr_o);
if ((addr & (align - 1)) != 0) {
mp_raise_ValueError_varg(translate("address %08x is not aligned to %d bytes"), addr, align);
}
return addr;
}
#if !defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)
#define MICROPY_MACHINE_MEM_GET_READ_ADDR machine_mem_get_addr
#endif
#if !defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR machine_mem_get_addr
#endif
#endif
STATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<%u-bit memory>", 8 * self->elem_size);
}
STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
// TODO support slice index to read/write multiple values at once
machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (value == MP_OBJ_NULL) {
// delete
return MP_OBJ_NULL; // op not supported
} else if (value == MP_OBJ_SENTINEL) {
// load
uintptr_t addr = MICROPY_MACHINE_MEM_GET_READ_ADDR(index, self->elem_size);
uint32_t val;
switch (self->elem_size) {
case 1:
val = (*(uint8_t *)addr);
break;
case 2:
val = (*(uint16_t *)addr);
break;
default:
val = (*(uint32_t *)addr);
break;
}
return mp_obj_new_int(val);
} else {
// store
uintptr_t addr = MICROPY_MACHINE_MEM_GET_WRITE_ADDR(index, self->elem_size);
uint32_t val = mp_obj_get_int_truncated(value);
switch (self->elem_size) {
case 1:
(*(uint8_t *)addr) = val;
break;
case 2:
(*(uint16_t *)addr) = val;
break;
default:
(*(uint32_t *)addr) = val;
break;
}
return mp_const_none;
}
}
const mp_obj_type_t machine_mem_type = {
{ &mp_type_type },
.name = MP_QSTR_mem,
.print = machine_mem_print,
.subscr = machine_mem_subscr,
};
const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1};
const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2};
const machine_mem_obj_t machine_mem32_obj = {{&machine_mem_type}, 4};
#endif // MICROPY_PY_MACHINE

View File

@ -1,29 +0,0 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2015 Damien P. George
//
// SPDX-License-Identifier: MIT
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
#include "py/obj.h"
typedef struct _machine_mem_obj_t {
mp_obj_base_t base;
unsigned elem_size; // in bytes
} machine_mem_obj_t;
extern const mp_obj_type_t machine_mem_type;
extern const machine_mem_obj_t machine_mem8_obj;
extern const machine_mem_obj_t machine_mem16_obj;
extern const machine_mem_obj_t machine_mem32_obj;
#if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)
uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align);
#endif
#if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align);
#endif
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H

View File

@ -1,67 +0,0 @@
// Copyright (c) 2016 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#include "py/mpconfig.h"
#if MICROPY_PY_MACHINE
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/virtpin.h"
#include "extmod/machine_pinbase.h"
// PinBase class
// As this is abstract class, its instance is null.
// But there should be an instance, as the rest of instance code
// expects that there will be concrete object for inheritance.
typedef struct _mp_pinbase_t {
mp_obj_base_t base;
} mp_pinbase_t;
STATIC const mp_pinbase_t pinbase_singleton = {
.base = { &machine_pinbase_type },
};
STATIC mp_obj_t pinbase_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
(void)type;
(void)n_args;
(void)args;
(void)kw_args;
return MP_OBJ_FROM_PTR(&pinbase_singleton);
}
mp_uint_t pinbase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
mp_uint_t pinbase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode) {
(void)errcode;
switch (request) {
case MP_PIN_READ: {
mp_obj_t dest[2];
mp_load_method(obj, MP_QSTR_value, dest);
return mp_obj_get_int(mp_call_method_n_kw(0, 0, dest));
}
case MP_PIN_WRITE: {
mp_obj_t dest[3];
mp_load_method(obj, MP_QSTR_value, dest);
dest[2] = (arg == 0 ? mp_const_false : mp_const_true);
mp_call_method_n_kw(1, 0, dest);
return 0;
}
}
return -1;
}
STATIC const mp_pin_p_t pinbase_pin_p = {
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_pin)
.ioctl = pinbase_ioctl,
};
const mp_obj_type_t machine_pinbase_type = {
{ &mp_type_type },
.name = MP_QSTR_PinBase,
.make_new = pinbase_make_new,
.protocol = &pinbase_pin_p,
};
#endif // MICROPY_PY_MACHINE

View File

@ -1,13 +0,0 @@
// Copyright (c) 2016 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
#include "py/obj.h"
extern const mp_obj_type_t machine_pinbase_type;
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H

View File

@ -1,44 +0,0 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
//
// SPDX-License-Identifier: MIT
#include "py/runtime.h"
#include "py/mperrno.h"
#include "extmod/machine_pulse.h"
#if MICROPY_PY_MACHINE_PULSE
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
mp_uint_t start = mp_hal_ticks_us();
while (mp_hal_pin_read(pin) != pulse_level) {
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
return (mp_uint_t)-2;
}
}
start = mp_hal_ticks_us();
while (mp_hal_pin_read(pin) == pulse_level) {
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
return (mp_uint_t)-1;
}
}
return mp_hal_ticks_us() - start;
}
STATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(args[0]);
int level = 0;
if (mp_obj_is_true(args[1])) {
level = 1;
}
mp_uint_t timeout_us = 1000000;
if (n_args > 2) {
timeout_us = mp_obj_get_int(args[2]);
}
mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us);
// May return -1 or -2 in case of timeout
return mp_obj_new_int(us);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_);
#endif

View File

@ -1,16 +0,0 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
//
// SPDX-License-Identifier: MIT
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H
#include "py/obj.h"
#include "py/mphal.h"
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj);
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H

View File

@ -1,159 +0,0 @@
// Copyright (c) 2017 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#include "py/mpconfig.h"
#if MICROPY_PY_MACHINE
#include <string.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/virtpin.h"
#include "extmod/machine_signal.h"
// Signal class
typedef struct _machine_signal_t {
mp_obj_base_t base;
mp_obj_t pin;
bool invert;
} machine_signal_t;
STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_obj_t pin = args[0];
bool invert = false;
#if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW)
mp_pin_p_t *pin_p = (mp_pin_t *)mp_proto_get(QSTR_pin_protocol, pin);
if (pin_p == NULL) {
// If first argument isn't a Pin-like object, we filter out "invert"
// from keyword arguments and pass them all to the exported Pin
// constructor to create one.
mp_obj_t *pin_args = mp_local_alloc((n_args + n_kw * 2) * sizeof(mp_obj_t));
memcpy(pin_args, args, n_args * sizeof(mp_obj_t));
const mp_obj_t *src = args + n_args;
mp_obj_t *dst = pin_args + n_args;
mp_obj_t *sig_value = NULL;
for (size_t cnt = n_kw; cnt; cnt--) {
if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) {
invert = mp_obj_is_true(src[1]);
n_kw--;
} else {
*dst++ = *src;
*dst++ = src[1];
}
if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_value)) {
// Value is pertained to Signal, so we should invert
// it for Pin if needed, and we should do it only when
// inversion status is guaranteedly known.
sig_value = dst - 1;
}
src += 2;
}
if (invert && sig_value != NULL) {
*sig_value = mp_obj_is_true(*sig_value) ? MP_OBJ_NEW_SMALL_INT(0) : MP_OBJ_NEW_SMALL_INT(1);
}
// Here we pass NULL as a type, hoping that mp_pin_make_new()
// will just ignore it as set a concrete type. If not, we'd need
// to expose port's "default" pin type too.
pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args);
mp_local_free(pin_args);
} else
#endif
// Otherwise there should be 1 or 2 args
{
if (n_args == 1) {
if (kw_args == NULL || kw_args->used == 0) {
} else if (kw_args->used == 1 && kw_args->table[0].key == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) {
invert = mp_obj_is_true(kw_args->table[0].value);
} else {
goto error;
}
} else {
error:
mp_raise_TypeError(NULL);
}
}
machine_signal_t *o = m_new_obj(machine_signal_t);
o->base.type = type;
o->pin = pin;
o->invert = invert;
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_uint_t signal_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
(void)errcode;
machine_signal_t *self = MP_OBJ_TO_PTR(self_in);
switch (request) {
case MP_PIN_READ: {
return mp_virtual_pin_read(self->pin) ^ self->invert;
}
case MP_PIN_WRITE: {
mp_virtual_pin_write(self->pin, arg ^ self->invert);
return 0;
}
}
return -1;
}
// fast method for getting/setting signal value
STATIC mp_obj_t signal_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num_kw_array(n_args, n_kw, 0, 1, false);
if (n_args == 0) {
// get pin
return MP_OBJ_NEW_SMALL_INT(mp_virtual_pin_read(self_in));
} else {
// set pin
mp_virtual_pin_write(self_in, mp_obj_is_true(args[0]));
return mp_const_none;
}
}
STATIC mp_obj_t signal_value(size_t n_args, const mp_obj_t *args) {
return signal_call(args[0], n_args - 1, 0, args + 1);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(signal_value_obj, 1, 2, signal_value);
STATIC mp_obj_t signal_on(mp_obj_t self_in) {
mp_virtual_pin_write(self_in, 1);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(signal_on_obj, signal_on);
STATIC mp_obj_t signal_off(mp_obj_t self_in) {
mp_virtual_pin_write(self_in, 0);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(signal_off_obj, signal_off);
STATIC const mp_rom_map_elem_t signal_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&signal_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&signal_on_obj) },
{ MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&signal_off_obj) },
};
STATIC MP_DEFINE_CONST_DICT(signal_locals_dict, signal_locals_dict_table);
STATIC const mp_pin_p_t signal_pin_p = {
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_pin)
.ioctl = signal_ioctl,
};
const mp_obj_type_t machine_signal_type = {
{ &mp_type_type },
.name = MP_QSTR_Signal,
.make_new = signal_make_new,
.call = signal_call,
.protocol = &signal_pin_p,
.locals_dict = (void *)&signal_locals_dict,
};
#endif // MICROPY_PY_MACHINE

View File

@ -1,13 +0,0 @@
// Copyright (c) 2017 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H
#include "py/obj.h"
extern const mp_obj_type_t machine_signal_type;
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SIGNAL_H

View File

@ -15,6 +15,7 @@
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
#if MICROPY_PY_OS_DUPTERM
bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream);
int mp_uos_dupterm_rx_chr(void);
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);

View File

@ -331,7 +331,7 @@ STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t
openinfo.psize = args.pagesize.u_int;
openinfo.minkeypage = args.minkeypage.u_int;
DB *db = __bt_open(pos_args[0], &btree_stream_fvtable, &openinfo, /*dflags*/ 0);
DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, /*dflags*/ 0);
if (db == NULL) {
mp_raise_OSError(errno);
}

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@
// Low-level 1-Wire routines
#define TIMING_RESET1 (480)
#define TIMING_RESET2 (40)
#define TIMING_RESET3 (420)
#define TIMING_RESET2 (70)
#define TIMING_RESET3 (410)
#define TIMING_READ1 (5)
#define TIMING_READ2 (5)
#define TIMING_READ3 (40)

View File

@ -13,7 +13,7 @@
static void check_not_unicode(const mp_obj_t arg) {
#if MICROPY_CPYTHON_COMPAT
if (MP_OBJ_IS_STR(arg)) {
if (mp_obj_is_str(arg)) {
mp_raise_TypeError(translate("a bytes-like object is required"));
}
#endif

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014 Paul Sokolovsky
// Copyright (c) 2014-2018 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
@ -73,7 +73,7 @@ enum {
#define AGG_TYPE_BITS 2
enum {
STRUCT, PTR, ARRAY, BITFIELD,
STRUCT, PTR, ARRAY,
};
// Here we need to set sign bit right
@ -118,9 +118,13 @@ STATIC void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_p
(void)kind;
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
const char *typen = "unk";
if (MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
if (mp_obj_is_type(self->desc, &mp_type_dict)
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
|| mp_obj_is_type(self->desc, &mp_type_ordereddict)
#endif
) {
typen = "STRUCT";
} else if (MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
} else if (mp_obj_is_type(self->desc, &mp_type_tuple)) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
@ -191,10 +195,14 @@ STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
}
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size) {
if (!MP_OBJ_IS_TYPE(desc_in, &mp_type_dict)) {
if (MP_OBJ_IS_TYPE(desc_in, &mp_type_tuple)) {
if (!mp_obj_is_type(desc_in, &mp_type_dict)
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
&& !mp_obj_is_type(desc_in, &mp_type_ordereddict)
#endif
) {
if (mp_obj_is_type(desc_in, &mp_type_tuple)) {
return uctypes_struct_agg_size((mp_obj_tuple_t *)MP_OBJ_TO_PTR(desc_in), layout_type, max_field_size);
} else if (MP_OBJ_IS_SMALL_INT(desc_in)) {
} else if (mp_obj_is_small_int(desc_in)) {
// We allow sizeof on both type definitions and structures/structure fields,
// but scalar structure field is lowered into native Python int, so all
// type info is lost. So, we cannot say if it's scalar type description,
@ -208,9 +216,9 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_
mp_uint_t total_size = 0;
for (mp_uint_t i = 0; i < d->map.alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(&d->map, i)) {
if (mp_map_slot_is_filled(&d->map, i)) {
mp_obj_t v = d->map.table[i].value;
if (MP_OBJ_IS_SMALL_INT(v)) {
if (mp_obj_is_small_int(v)) {
mp_uint_t offset = MP_OBJ_SMALL_INT_VALUE(v);
mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS);
offset &= VALUE_MASK(VAL_TYPE_BITS);
@ -225,7 +233,7 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_
total_size = offset + s;
}
} else {
if (!MP_OBJ_IS_TYPE(v, &mp_type_tuple)) {
if (!mp_obj_is_type(v, &mp_type_tuple)) {
syntax_error();
}
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(v);
@ -246,24 +254,32 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_
return total_size;
}
STATIC mp_obj_t uctypes_struct_sizeof(mp_obj_t obj_in) {
STATIC mp_obj_t uctypes_struct_sizeof(size_t n_args, const mp_obj_t *args) {
mp_obj_t obj_in = args[0];
mp_uint_t max_field_size = 0;
if (MP_OBJ_IS_TYPE(obj_in, &mp_type_bytearray)) {
if (mp_obj_is_type(obj_in, &mp_type_bytearray)) {
return mp_obj_len(obj_in);
}
int layout_type = LAYOUT_NATIVE;
// We can apply sizeof either to structure definition (a dict)
// or to instantiated structure
if (MP_OBJ_IS_TYPE(obj_in, &uctypes_struct_type)) {
if (mp_obj_is_type(obj_in, &uctypes_struct_type)) {
if (n_args != 1) {
mp_raise_TypeError(NULL);
}
// Extract structure definition
mp_obj_uctypes_struct_t *obj = MP_OBJ_TO_PTR(obj_in);
obj_in = obj->desc;
layout_type = obj->flags;
} else {
if (n_args == 2) {
layout_type = mp_obj_get_int(args[1]);
}
}
mp_uint_t size = uctypes_struct_size(obj_in, layout_type, &max_field_size);
return MP_OBJ_NEW_SMALL_INT(size);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_sizeof_obj, uctypes_struct_sizeof);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uctypes_struct_sizeof_obj, 1, 2, uctypes_struct_sizeof);
static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) {
char struct_type = big_endian ? '>' : '<';
@ -325,7 +341,7 @@ STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) {
return mp_obj_new_int_from_ll(((int64_t *)p)[index]);
#if MICROPY_PY_BUILTINS_FLOAT
case FLOAT32:
return mp_obj_new_float((mp_float_t)((float *)p)[index]);
return mp_obj_new_float(((float *)p)[index]);
case FLOAT64:
return mp_obj_new_float(((double *)p)[index]);
#endif
@ -384,13 +400,16 @@ STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set_val) {
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
// TODO: Support at least OrderedDict in addition
if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
if (!mp_obj_is_type(self->desc, &mp_type_dict)
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
&& !mp_obj_is_type(self->desc, &mp_type_ordereddict)
#endif
) {
mp_raise_TypeError(translate("struct: no fields"));
}
mp_obj_t deref = mp_obj_dict_get(self->desc, MP_OBJ_NEW_QSTR(attr));
if (MP_OBJ_IS_SMALL_INT(deref)) {
if (mp_obj_is_small_int(deref)) {
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(deref);
mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS);
offset &= VALUE_MASK(VAL_TYPE_BITS);
@ -451,7 +470,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
return MP_OBJ_NULL;
}
if (!MP_OBJ_IS_TYPE(deref, &mp_type_tuple)) {
if (!mp_obj_is_type(deref, &mp_type_tuple)) {
syntax_error();
}
@ -518,7 +537,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
return MP_OBJ_NULL; // op not supported
} else {
// load / store
if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
if (!mp_obj_is_type(self->desc, &mp_type_tuple)) {
mp_raise_TypeError(translate("struct: cannot index"));
}
@ -569,7 +588,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
} else if (agg_type == PTR) {
byte *p = *(void **)self->addr;
if (MP_OBJ_IS_SMALL_INT(t->items[1])) {
if (mp_obj_is_small_int(t->items[1])) {
uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS);
return get_aligned(val_type, p, index);
} else {
@ -589,6 +608,26 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
}
}
STATIC mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
switch (op) {
case MP_UNARY_OP_INT:
if (mp_obj_is_type(self->desc, &mp_type_tuple)) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
if (agg_type == PTR) {
byte *p = *(void **)self->addr;
return mp_obj_new_int((mp_int_t)(uintptr_t)p);
}
}
/* fallthru */
default:
return MP_OBJ_NULL; // op not supported
}
}
STATIC mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
(void)flags;
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
@ -637,6 +676,7 @@ STATIC const mp_obj_type_t uctypes_struct_type = {
.make_new = uctypes_struct_make_new,
.attr = uctypes_struct_attr,
.subscr = uctypes_struct_subscr,
.unary_op = uctypes_struct_unary_op,
.buffer_p = { .get_buffer = uctypes_get_buffer },
};
@ -695,6 +735,30 @@ STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_FLOAT64), MP_ROM_INT(TYPE2SMALLINT(FLOAT64, 4)) },
#endif
#if MICROPY_PY_UCTYPES_NATIVE_C_TYPES
// C native type aliases. These depend on GCC-compatible predefined
// preprocessor macros.
#if __SIZEOF_SHORT__ == 2
{ MP_ROM_QSTR(MP_QSTR_SHORT), MP_ROM_INT(TYPE2SMALLINT(INT16, 4)) },
{ MP_ROM_QSTR(MP_QSTR_USHORT), MP_ROM_INT(TYPE2SMALLINT(UINT16, 4)) },
#endif
#if __SIZEOF_INT__ == 4
{ MP_ROM_QSTR(MP_QSTR_INT), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_UINT), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) },
#endif
#if __SIZEOF_LONG__ == 4
{ MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) },
#elif __SIZEOF_LONG__ == 8
{ MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) },
{ MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) },
#endif
#if __SIZEOF_LONG_LONG__ == 8
{ MP_ROM_QSTR(MP_QSTR_LONGLONG), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) },
{ MP_ROM_QSTR(MP_QSTR_ULONGLONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) },
#endif
#endif // MICROPY_PY_UCTYPES_NATIVE_C_TYPES
{ MP_ROM_QSTR(MP_QSTR_PTR), MP_ROM_INT(TYPE2SMALLINT(PTR, AGG_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_ARRAY), MP_ROM_INT(TYPE2SMALLINT(ARRAY, AGG_TYPE_BITS)) },
};

View File

@ -12,6 +12,10 @@
#if MICROPY_PY_UHASHLIB
#if MICROPY_SSL_MBEDTLS
#include "mbedtls/version.h"
#endif
#if MICROPY_PY_UHASHLIB_SHA256
#if MICROPY_SSL_MBEDTLS
@ -22,13 +26,14 @@
#endif
#if MICROPY_PY_UHASHLIB_SHA1
#if MICROPY_PY_UHASHLIB_SHA1 || MICROPY_PY_UHASHLIB_MD5
#if MICROPY_SSL_AXTLS
#include "lib/axtls/crypto/crypto.h"
#endif
#if MICROPY_SSL_MBEDTLS
#include "mbedtls/md5.h"
#include "mbedtls/sha1.h"
#endif
@ -45,12 +50,18 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
#if MICROPY_SSL_MBEDTLS
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 0, 1, false);
#if MBEDTLS_VERSION_NUMBER < 0x02070000
#define mbedtls_sha256_starts_ret mbedtls_sha256_starts
#define mbedtls_sha256_update_ret mbedtls_sha256_update
#define mbedtls_sha256_finish_ret mbedtls_sha256_finish
#endif
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context));
o->base.type = type;
mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
mbedtls_sha256_starts((mbedtls_sha256_context *)&o->state, 0);
mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
if (n_args == 1) {
uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@ -61,7 +72,7 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
mbedtls_sha256_update((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
mbedtls_sha256_update_ret((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@ -69,7 +80,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, 32);
mbedtls_sha256_finish((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
@ -77,12 +88,16 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
static void check_not_unicode(const mp_obj_t arg) {
#if MICROPY_CPYTHON_COMPAT
if (MP_OBJ_IS_STR(arg)) {
if (mp_obj_is_str(arg)) {
mp_raise_TypeError(translate("a bytes-like object is required"));
}
#endif
}
#if MICROPY_PY_UHASHLIB_SHA256
#include "crypto-algorithms/sha256.c"
#endif
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX));
@ -164,12 +179,19 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
#endif
#if MICROPY_SSL_MBEDTLS
#if MBEDTLS_VERSION_NUMBER < 0x02070000
#define mbedtls_sha1_starts_ret mbedtls_sha1_starts
#define mbedtls_sha1_update_ret mbedtls_sha1_update
#define mbedtls_sha1_finish_ret mbedtls_sha1_finish
#endif
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context));
o->base.type = type;
mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
mbedtls_sha1_starts((mbedtls_sha1_context *)o->state);
mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
if (n_args == 1) {
uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@ -180,7 +202,7 @@ STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
mbedtls_sha1_update((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
mbedtls_sha1_update_ret((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@ -188,7 +210,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, 20);
mbedtls_sha1_finish((mbedtls_sha1_context *)self->state, (byte *)vstr.buf);
mbedtls_sha1_finish_ret((mbedtls_sha1_context *)self->state, (byte *)vstr.buf);
mbedtls_sha1_free((mbedtls_sha1_context *)self->state);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
@ -211,6 +233,93 @@ STATIC const mp_obj_type_t uhashlib_sha1_type = {
};
#endif
#if MICROPY_PY_UHASHLIB_MD5
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg);
#if MICROPY_SSL_AXTLS
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(MD5_CTX));
o->base.type = type;
MD5_Init((MD5_CTX *)o->state);
if (n_args == 1) {
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
}
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
MD5_Update((MD5_CTX *)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, MD5_SIZE);
MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
#endif // MICROPY_SSL_AXTLS
#if MICROPY_SSL_MBEDTLS
#if MBEDTLS_VERSION_NUMBER < 0x02070000
#define mbedtls_md5_starts_ret mbedtls_md5_starts
#define mbedtls_md5_update_ret mbedtls_md5_update
#define mbedtls_md5_finish_ret mbedtls_md5_finish
#endif
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context));
o->base.type = type;
mbedtls_md5_init((mbedtls_md5_context *)o->state);
mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
if (n_args == 1) {
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
}
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
mbedtls_md5_update_ret((mbedtls_md5_context *)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, 16);
mbedtls_md5_finish_ret((mbedtls_md5_context *)self->state, (byte *)vstr.buf);
mbedtls_md5_free((mbedtls_md5_context *)self->state);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
#endif // MICROPY_SSL_MBEDTLS
STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_md5_update_obj, uhashlib_md5_update);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_md5_digest_obj, uhashlib_md5_digest);
STATIC const mp_rom_map_elem_t uhashlib_md5_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_md5_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_md5_digest_obj) },
};
STATIC MP_DEFINE_CONST_DICT(uhashlib_md5_locals_dict, uhashlib_md5_locals_dict_table);
STATIC const mp_obj_type_t uhashlib_md5_type = {
{ &mp_type_type },
.name = MP_QSTR_md5,
.make_new = uhashlib_md5_make_new,
.locals_dict = (void *)&uhashlib_md5_locals_dict,
};
#endif // MICROPY_PY_UHASHLIB_MD5
STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hashlib) },
#if MICROPY_PY_UHASHLIB_SHA256
@ -219,6 +328,9 @@ STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = {
#if MICROPY_PY_UHASHLIB_SHA1
{ MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&uhashlib_sha1_type) },
#endif
#if MICROPY_PY_UHASHLIB_MD5
{ MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&uhashlib_md5_type) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_uhashlib_globals, mp_module_uhashlib_globals_table);
@ -228,8 +340,4 @@ const mp_obj_module_t mp_module_uhashlib = {
.globals = (mp_obj_dict_t *)&mp_module_uhashlib_globals,
};
#if MICROPY_PY_UHASHLIB_SHA256
#include "crypto-algorithms/sha256.c"
#endif
#endif // MICROPY_PY_UHASHLIB

View File

@ -13,7 +13,7 @@
// the algorithm here is modelled on CPython's heapq.py
STATIC mp_obj_list_t *get_heap(mp_obj_t heap_in) {
if (!MP_OBJ_IS_TYPE(heap_in, &mp_type_list)) {
if (!mp_obj_is_type(heap_in, &mp_type_list)) {
mp_raise_TypeError(translate("heap must be a list"));
}
return MP_OBJ_TO_PTR(heap_in);

View File

@ -243,7 +243,7 @@ STATIC mp_obj_t _mod_ujson_load(mp_obj_t stream_obj, bool return_first_json) {
cur = S_CUR(s);
if (cur == '.' || cur == 'E' || cur == 'e') {
flt = true;
} else if (cur == '-' || unichar_isdigit(cur)) {
} else if (cur == '+' || cur == '-' || unichar_isdigit(cur)) {
// pass
} else {
break;

View File

@ -180,8 +180,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_uniform_obj, mod_urandom_uniform);
#endif // MICROPY_PY_URANDOM_EXTRA_FUNCS
#ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC
STATIC mp_obj_t mod_urandom___init__() {
mod_urandom_seed(MP_OBJ_NEW_SMALL_INT(MICROPY_PY_URANDOM_SEED_INIT_FUNC));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_urandom___init___obj, mod_urandom___init__);
#endif
STATIC const mp_rom_map_elem_t mp_module_urandom_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_urandom) },
#ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&mod_urandom___init___obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_getrandbits), MP_ROM_PTR(&mod_urandom_getrandbits_obj) },
{ MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_urandom_seed_obj) },
#if MICROPY_PY_URANDOM_EXTRA_FUNCS

View File

@ -1,5 +1,6 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
// SPDX-FileCopyrightText: Copyright (c) 2015-2017 Paul Sokolovsky
//
// SPDX-License-Identifier: MIT
@ -25,7 +26,7 @@
typedef struct _poll_obj_t {
mp_obj_t obj;
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, mp_uint_t arg, int *errcode);
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
mp_uint_t flags;
mp_uint_t flags_ret;
} poll_obj_t;
@ -33,7 +34,7 @@ typedef struct _poll_obj_t {
STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) {
for (mp_uint_t i = 0; i < obj_len; i++) {
mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
if (elem->value == NULL) {
if (elem->value == MP_OBJ_NULL) {
// object not found; get its ioctl and add it to the poll list
const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL);
poll_obj_t *poll_obj = m_new_obj(poll_obj_t);
@ -41,27 +42,27 @@ STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_
poll_obj->ioctl = stream_p->ioctl;
poll_obj->flags = flags;
poll_obj->flags_ret = 0;
elem->value = poll_obj;
elem->value = MP_OBJ_FROM_PTR(poll_obj);
} else {
// object exists; update its flags
if (or_flags) {
((poll_obj_t *)elem->value)->flags |= flags;
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags |= flags;
} else {
((poll_obj_t *)elem->value)->flags = flags;
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = flags;
}
}
}
}
// poll each object in the map
STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, mp_uint_t *rwx_num) {
STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) {
mp_uint_t n_ready = 0;
for (mp_uint_t i = 0; i < poll_map->alloc; ++i) {
if (!MP_MAP_SLOT_IS_FILLED(poll_map, i)) {
if (!mp_map_slot_is_filled(poll_map, i)) {
continue;
}
poll_obj_t *poll_obj = (poll_obj_t *)poll_map->table[i].value;
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map->table[i].value);
int errcode;
mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj->flags, &errcode);
poll_obj->flags_ret = ret;
@ -91,7 +92,7 @@ STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, mp_uint_t *rwx_num) {
}
/// \function select(rlist, wlist, xlist[, timeout])
STATIC mp_obj_t select_select(uint n_args, const mp_obj_t *args) {
STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
// get array data from tuple/list arguments
size_t rwx_len[3];
mp_obj_t *r_array, *w_array, *x_array;
@ -135,18 +136,18 @@ STATIC mp_obj_t select_select(uint n_args, const mp_obj_t *args) {
list_array[2] = mp_obj_new_list(rwx_len[2], NULL);
rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
for (mp_uint_t i = 0; i < poll_map.alloc; ++i) {
if (!MP_MAP_SLOT_IS_FILLED(&poll_map, i)) {
if (!mp_map_slot_is_filled(&poll_map, i)) {
continue;
}
poll_obj_t *poll_obj = (poll_obj_t *)poll_map.table[i].value;
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map.table[i].value);
if (poll_obj->flags_ret & MP_STREAM_POLL_RD) {
((mp_obj_list_t *)list_array[0])->items[rwx_len[0]++] = poll_obj->obj;
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj;
}
if (poll_obj->flags_ret & MP_STREAM_POLL_WR) {
((mp_obj_list_t *)list_array[1])->items[rwx_len[1]++] = poll_obj->obj;
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj;
}
if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
((mp_obj_list_t *)list_array[2])->items[rwx_len[2]++] = poll_obj->obj;
((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj;
}
}
mp_map_deinit(&poll_map);
@ -170,8 +171,8 @@ typedef struct _mp_obj_poll_t {
} mp_obj_poll_t;
/// \method register(obj[, eventmask])
STATIC mp_obj_t poll_register(uint n_args, const mp_obj_t *args) {
mp_obj_poll_t *self = args[0];
STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) {
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
mp_uint_t flags;
if (n_args == 3) {
flags = mp_obj_get_int(args[2]);
@ -185,7 +186,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
/// \method unregister(obj)
STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
mp_obj_poll_t *self = self_in;
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
// TODO raise KeyError if obj didn't exist in map
return mp_const_none;
@ -194,18 +195,18 @@ MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
/// \method modify(obj, eventmask)
STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
mp_obj_poll_t *self = self_in;
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP);
if (elem == NULL) {
mp_raise_OSError(MP_ENOENT);
}
((poll_obj_t *)elem->value)->flags = mp_obj_get_int(eventmask_in);
((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
mp_obj_poll_t *self = args[0];
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
// work out timeout (its given already in ms)
mp_uint_t timeout = -1;
@ -238,18 +239,18 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
return n_ready;
}
STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
mp_obj_poll_t *self = args[0];
STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) {
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
mp_uint_t n_ready = poll_poll_internal(n_args, args);
// one or more objects are ready, or we had a timeout
mp_obj_list_t *ret_list = mp_obj_new_list(n_ready, NULL);
mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL));
n_ready = 0;
for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) {
if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) {
if (!mp_map_slot_is_filled(&self->poll_map, i)) {
continue;
}
poll_obj_t *poll_obj = (poll_obj_t *)self->poll_map.table[i].value;
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
if (poll_obj->flags_ret != 0) {
mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)};
ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple);
@ -259,7 +260,7 @@ STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
}
}
}
return ret_list;
return MP_OBJ_FROM_PTR(ret_list);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
@ -289,10 +290,10 @@ STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
for (mp_uint_t i = self->iter_idx; i < self->poll_map.alloc; ++i) {
self->iter_idx++;
if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) {
if (!mp_map_slot_is_filled(&self->poll_map, i)) {
continue;
}
poll_obj_t *poll_obj = (poll_obj_t *)self->poll_map.table[i].value;
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
if (poll_obj->flags_ret != 0) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
t->items[0] = poll_obj->obj;
@ -334,7 +335,7 @@ STATIC mp_obj_t select_poll(void) {
mp_map_init(&poll->poll_map, 0);
poll->iter_cnt = 0;
poll->ret_tuple = MP_OBJ_NULL;
return poll;
return MP_OBJ_FROM_PTR(poll);
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll);

View File

@ -1,252 +0,0 @@
// Copyright (c) 2015-2017 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <string.h>
#include "py/runtime.h"
#include "py/stream.h"
#include "supervisor/shared/translate.h"
#if MICROPY_PY_USSL && MICROPY_SSL_AXTLS
#include "ssl.h"
typedef struct _mp_obj_ssl_socket_t {
mp_obj_base_t base;
mp_obj_t sock;
SSL_CTX *ssl_ctx;
SSL *ssl_sock;
byte *buf;
uint32_t bytes_left;
} mp_obj_ssl_socket_t;
struct ssl_args {
mp_arg_val_t key;
mp_arg_val_t cert;
mp_arg_val_t server_side;
mp_arg_val_t server_hostname;
};
STATIC const mp_obj_type_t ussl_socket_type;
STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
#if MICROPY_PY_USSL_FINALISER
mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
#else
mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
#endif
o->base.type = &ussl_socket_type;
o->buf = NULL;
o->bytes_left = 0;
o->sock = sock;
uint32_t options = SSL_SERVER_VERIFY_LATER;
if (args->key.u_obj != mp_const_none) {
options |= SSL_NO_DEFAULT_KEY;
}
if ((o->ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) {
mp_raise_OSError(MP_EINVAL);
}
if (args->key.u_obj != mp_const_none) {
size_t len;
const byte *data = (const byte *)mp_obj_str_get_data(args->key.u_obj, &len);
int res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_RSA_KEY, data, len, NULL);
if (res != SSL_OK) {
mp_raise_ValueError(translate("invalid key"));
}
data = (const byte *)mp_obj_str_get_data(args->cert.u_obj, &len);
res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_X509_CERT, data, len, NULL);
if (res != SSL_OK) {
mp_raise_ValueError(translate("invalid cert"));
}
}
if (args->server_side.u_bool) {
o->ssl_sock = ssl_server_new(o->ssl_ctx, (long)sock);
} else {
SSL_EXTENSIONS *ext = ssl_ext_new();
if (args->server_hostname.u_obj != mp_const_none) {
ext->host_name = (char *)mp_obj_str_get_str(args->server_hostname.u_obj);
}
o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0, ext);
int res = ssl_handshake_status(o->ssl_sock);
// Pointer to SSL_EXTENSIONS as being passed to ssl_client_new()
// is saved in ssl_sock->extensions.
// As of axTLS 2.1.3, extensions aren't used beyond the initial
// handshake, and that's pretty much how it's expected to be. So
// we allocate them on stack and reset the pointer after handshake.
if (res != SSL_OK) {
printf("ssl_handshake_status: %d\n", res);
ssl_display_error(res);
mp_raise_OSError(MP_EIO);
}
}
return o;
}
STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<_SSLSocket %p>", self->ssl_sock);
}
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
if (o->ssl_sock == NULL) {
*errcode = EBADF;
return MP_STREAM_ERROR;
}
while (o->bytes_left == 0) {
mp_int_t r = ssl_read(o->ssl_sock, &o->buf);
if (r == SSL_OK) {
// SSL_OK from ssl_read() means "everything is ok, but there's
// no user data yet". So, we just keep reading.
continue;
}
if (r < 0) {
if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) {
// EOF
return 0;
}
if (r == SSL_EAGAIN) {
r = MP_EAGAIN;
}
*errcode = r;
return MP_STREAM_ERROR;
}
o->bytes_left = r;
}
if (size > o->bytes_left) {
size = o->bytes_left;
}
memcpy(buf, o->buf, size);
o->buf += size;
o->bytes_left -= size;
return size;
}
STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
if (o->ssl_sock == NULL) {
*errcode = EBADF;
return MP_STREAM_ERROR;
}
mp_int_t r = ssl_write(o->ssl_sock, buf, size);
if (r < 0) {
*errcode = r;
return MP_STREAM_ERROR;
}
return r;
}
STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
(void)arg;
switch (request) {
case MP_STREAM_CLOSE:
if (self->ssl_sock != NULL) {
ssl_free(self->ssl_sock);
ssl_ctx_free(self->ssl_ctx);
self->ssl_sock = NULL;
mp_stream_close(self->sock);
}
return 0;
default:
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
}
STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
// Currently supports only blocking mode
(void)self_in;
if (!mp_obj_is_true(flag_in)) {
mp_raise_NotImplementedError(NULL);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
#if MICROPY_PY_USSL_FINALISER
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
STATIC const mp_stream_p_t ussl_socket_stream_p = {
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = socket_read,
.write = socket_write,
.ioctl = socket_ioctl,
};
STATIC const mp_obj_type_t ussl_socket_type = {
{ &mp_type_type },
// Save on qstr's, reuse same as for module
.name = MP_QSTR_ussl,
.print = socket_print,
.getiter = NULL,
.iternext = NULL,
.protocol = &ussl_socket_stream_p,
.locals_dict = (void *)&ussl_socket_locals_dict,
};
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// TODO: Implement more args
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
// TODO: Check that sock implements stream protocol
mp_obj_t sock = pos_args[0];
struct ssl_args args;
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
return MP_OBJ_FROM_PTR(socket_new(sock, &args));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
const mp_obj_module_t mp_module_ussl = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
};
#endif // MICROPY_PY_USSL

View File

@ -1,336 +0,0 @@
// Copyright (c) 2016 Linaro Ltd.
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#include "py/mpconfig.h"
#if MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS
#include <stdio.h>
#include <string.h>
#include <errno.h> // needed because mp_is_nonblocking_error uses system error codes
#include "py/runtime.h"
#include "py/stream.h"
// mbedtls_time_t
#include "mbedtls/platform.h"
#include "mbedtls/net.h"
#include "mbedtls/ssl.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/pk.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"
typedef struct _mp_obj_ssl_socket_t {
mp_obj_base_t base;
mp_obj_t sock;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
mbedtls_x509_crt cert;
mbedtls_pk_context pkey;
} mp_obj_ssl_socket_t;
struct ssl_args {
mp_arg_val_t key;
mp_arg_val_t cert;
mp_arg_val_t server_side;
mp_arg_val_t server_hostname;
};
STATIC const mp_obj_type_t ussl_socket_type;
#ifdef MBEDTLS_DEBUG_C
STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
(void)ctx;
(void)level;
printf("DBG:%s:%04d: %s\n", file, line, str);
}
#endif
STATIC int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
mp_obj_t sock = *(mp_obj_t *)ctx;
const mp_stream_p_t *sock_stream = mp_get_stream(sock);
int err;
mp_uint_t out_sz = sock_stream->write(sock, buf, len, &err);
if (out_sz == MP_STREAM_ERROR) {
if (mp_is_nonblocking_error(err)) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
return -err;
} else {
return out_sz;
}
}
STATIC int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
mp_obj_t sock = *(mp_obj_t *)ctx;
const mp_stream_p_t *sock_stream = mp_get_stream(sock);
int err;
mp_uint_t out_sz = sock_stream->read(sock, buf, len, &err);
if (out_sz == MP_STREAM_ERROR) {
if (mp_is_nonblocking_error(err)) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
return -err;
} else {
return out_sz;
}
}
STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
// Verify the socket object has the full stream protocol
mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
#if MICROPY_PY_USSL_FINALISER
mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
#else
mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
#endif
o->base.type = &ussl_socket_type;
o->sock = sock;
int ret;
mbedtls_ssl_init(&o->ssl);
mbedtls_ssl_config_init(&o->conf);
mbedtls_x509_crt_init(&o->cacert);
mbedtls_x509_crt_init(&o->cert);
mbedtls_pk_init(&o->pkey);
mbedtls_ctr_drbg_init(&o->ctr_drbg);
#ifdef MBEDTLS_DEBUG_C
// Debug level (0-4)
mbedtls_debug_set_threshold(0);
#endif
mbedtls_entropy_init(&o->entropy);
const byte seed[] = "upy";
ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, mbedtls_entropy_func, &o->entropy, seed, sizeof(seed));
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_ssl_config_defaults(&o->conf,
args->server_side.u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (ret != 0) {
goto cleanup;
}
mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg);
#ifdef MBEDTLS_DEBUG_C
mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL);
#endif
ret = mbedtls_ssl_setup(&o->ssl, &o->conf);
if (ret != 0) {
goto cleanup;
}
if (args->server_hostname.u_obj != mp_const_none) {
const char *sni = mp_obj_str_get_str(args->server_hostname.u_obj);
ret = mbedtls_ssl_set_hostname(&o->ssl, sni);
if (ret != 0) {
goto cleanup;
}
}
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
if (args->key.u_obj != MP_OBJ_NULL) {
size_t key_len;
const byte *key = (const byte *)mp_obj_str_get_data(args->key.u_obj, &key_len);
// len should include terminating null
ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0);
assert(ret == 0);
size_t cert_len;
const byte *cert = (const byte *)mp_obj_str_get_data(args->cert.u_obj, &cert_len);
// len should include terminating null
ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1);
assert(ret == 0);
ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey);
assert(ret == 0);
}
while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
printf("mbedtls_ssl_handshake error: -%x\n", -ret);
goto cleanup;
}
}
return o;
cleanup:
mbedtls_pk_free(&o->pkey);
mbedtls_x509_crt_free(&o->cert);
mbedtls_x509_crt_free(&o->cacert);
mbedtls_ssl_free(&o->ssl);
mbedtls_ssl_config_free(&o->conf);
mbedtls_ctr_drbg_free(&o->ctr_drbg);
mbedtls_entropy_free(&o->entropy);
if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
mp_raise_OSError(MP_ENOMEM);
} else {
mp_raise_OSError(MP_EIO);
}
}
STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
if (!mp_obj_is_true(binary_form)) {
mp_raise_NotImplementedError(NULL);
}
const mbedtls_x509_crt *peer_cert = mbedtls_ssl_get_peer_cert(&o->ssl);
return mp_obj_new_bytes(peer_cert->raw.p, peer_cert->raw.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert);
STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<_SSLSocket %p>", self);
}
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
int ret = mbedtls_ssl_read(&o->ssl, buf, size);
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
// end of stream
return 0;
}
if (ret >= 0) {
return ret;
}
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
ret = MP_EWOULDBLOCK;
}
*errcode = ret;
return MP_STREAM_ERROR;
}
STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
int ret = mbedtls_ssl_write(&o->ssl, buf, size);
if (ret >= 0) {
return ret;
}
if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = MP_EWOULDBLOCK;
}
*errcode = ret;
return MP_STREAM_ERROR;
}
STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in);
mp_obj_t sock = o->sock;
mp_obj_t dest[3];
mp_load_method(sock, MP_QSTR_setblocking, dest);
dest[2] = flag_in;
return mp_call_method_n_kw(1, 0, dest);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
(void)arg;
switch (request) {
case MP_STREAM_CLOSE:
mbedtls_pk_free(&self->pkey);
mbedtls_x509_crt_free(&self->cert);
mbedtls_x509_crt_free(&self->cacert);
mbedtls_ssl_free(&self->ssl);
mbedtls_ssl_config_free(&self->conf);
mbedtls_ctr_drbg_free(&self->ctr_drbg);
mbedtls_entropy_free(&self->entropy);
mp_stream_close(self->sock);
return 0;
default:
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
}
STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
#if MICROPY_PY_USSL_FINALISER
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
};
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
STATIC const mp_stream_p_t ussl_socket_stream_p = {
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = socket_read,
.write = socket_write,
.ioctl = socket_ioctl,
};
STATIC const mp_obj_type_t ussl_socket_type = {
{ &mp_type_type },
// Save on qstr's, reuse same as for module
.name = MP_QSTR_ussl,
.print = socket_print,
.getiter = NULL,
.iternext = NULL,
.protocol = &ussl_socket_stream_p,
.locals_dict = (void *)&ussl_socket_locals_dict,
};
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// TODO: Implement more args
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
// TODO: Check that sock implements stream protocol
mp_obj_t sock = pos_args[0];
struct ssl_args args;
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
return MP_OBJ_FROM_PTR(socket_new(sock, &args));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
const mp_obj_module_t mp_module_ussl = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
};
#endif // MICROPY_PY_USSL

View File

@ -126,7 +126,7 @@ STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) {
mp_raise_IndexError(translate("empty heap"));
}
mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref);
if (!MP_OBJ_IS_TYPE(list_ref, &mp_type_list) || ret->len < 3) {
if (!mp_obj_is_type(list_ref, &mp_type_list) || ret->len < 3) {
mp_raise_TypeError(NULL);
}

10
extmod/moduwebsocket.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H
#define MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H
#define FRAME_OPCODE_MASK 0x0f
enum {
FRAME_CONT, FRAME_TXT, FRAME_BIN,
FRAME_CLOSE = 0x8, FRAME_PING, FRAME_PONG
};
#endif // MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H

View File

@ -13,8 +13,7 @@
#ifdef MICROPY_PY_WEBREPL_DELAY
#include "py/mphal.h"
#endif
#include "extmod/modwebsocket.h"
#include "genhdr/mpversion.h"
#include "extmod/moduwebsocket.h"
#if MICROPY_PY_WEBREPL
@ -88,6 +87,15 @@ STATIC mp_obj_t webrepl_make_new(const mp_obj_type_t *type, size_t n_args, size_
return o;
}
STATIC void check_file_op_finished(mp_obj_webrepl_t *self) {
if (self->data_to_recv == 0) {
mp_stream_close(self->cur_file);
self->hdr_to_recv = sizeof(struct webrepl_file);
DEBUG_printf("webrepl: Finished file operation %d\n", self->hdr.type);
write_webrepl_resp(self->sock, 0);
}
}
STATIC int write_file_chunk(mp_obj_webrepl_t *self) {
const mp_stream_p_t *file_stream = mp_get_stream(self->cur_file);
byte readbuf[2 + 256];
@ -140,6 +148,7 @@ STATIC void handle_op(mp_obj_webrepl_t *self) {
if (self->hdr.type == PUT_FILE) {
self->data_to_recv = self->hdr.size;
check_file_op_finished(self);
} else if (self->hdr.type == GET_FILE) {
self->data_to_recv = 1;
}
@ -246,12 +255,7 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
}
}
if (self->data_to_recv == 0) {
mp_stream_close(self->cur_file);
self->hdr_to_recv = sizeof(struct webrepl_file);
DEBUG_printf("webrepl: Finished file operation %d\n", self->hdr.type);
write_webrepl_resp(self->sock, 0);
}
check_file_op_finished(self);
#ifdef MICROPY_PY_WEBREPL_DELAY
// Some platforms may have broken drivers and easily gets

View File

@ -1,294 +0,0 @@
// Copyright (c) 2016 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "py/runtime.h"
#include "py/stream.h"
#include "extmod/modwebsocket.h"
#if MICROPY_PY_WEBSOCKET
enum { FRAME_HEADER, FRAME_OPT, PAYLOAD, CONTROL };
enum { BLOCKING_WRITE = 0x80 };
typedef struct _mp_obj_websocket_t {
mp_obj_base_t base;
mp_obj_t sock;
uint32_t msg_sz;
byte mask[4];
byte state;
byte to_recv;
byte mask_pos;
byte buf_pos;
byte buf[6];
byte opts;
// Copy of last data frame flags
byte ws_flags;
// Copy of current frame flags
byte last_flags;
} mp_obj_websocket_t;
STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode);
STATIC mp_obj_t websocket_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 1, 2, false);
mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
mp_obj_websocket_t *o = m_new_obj(mp_obj_websocket_t);
o->base.type = type;
o->sock = args[0];
o->state = FRAME_HEADER;
o->to_recv = 2;
o->mask_pos = 0;
o->buf_pos = 0;
o->opts = FRAME_TXT;
if (n_args > 1 && args[1] == mp_const_true) {
o->opts |= BLOCKING_WRITE;
}
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
const mp_stream_p_t *stream_p = mp_get_stream(self->sock);
while (1) {
if (self->to_recv != 0) {
mp_uint_t out_sz = stream_p->read(self->sock, self->buf + self->buf_pos, self->to_recv, errcode);
if (out_sz == 0 || out_sz == MP_STREAM_ERROR) {
return out_sz;
}
self->buf_pos += out_sz;
self->to_recv -= out_sz;
if (self->to_recv != 0) {
*errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
}
switch (self->state) {
case FRAME_HEADER: {
// TODO: Split frame handling below is untested so far, so conservatively disable it
assert(self->buf[0] & 0x80);
// "Control frames MAY be injected in the middle of a fragmented message."
// So, they must be processed before data frames (and not alter
// self->ws_flags)
byte frame_type = self->buf[0];
self->last_flags = frame_type;
frame_type &= FRAME_OPCODE_MASK;
if ((self->buf[0] & FRAME_OPCODE_MASK) == FRAME_CONT) {
// Preserve previous frame type
self->ws_flags = (self->ws_flags & FRAME_OPCODE_MASK) | (self->buf[0] & ~FRAME_OPCODE_MASK);
} else {
self->ws_flags = self->buf[0];
}
// Reset mask in case someone will use "simplified" protocol
// without masks.
memset(self->mask, 0, sizeof(self->mask));
int to_recv = 0;
size_t sz = self->buf[1] & 0x7f;
if (sz == 126) {
// Msg size is next 2 bytes
to_recv += 2;
} else if (sz == 127) {
// Msg size is next 8 bytes
assert(0);
}
if (self->buf[1] & 0x80) {
// Next 4 bytes is mask
to_recv += 4;
}
self->buf_pos = 0;
self->to_recv = to_recv;
self->msg_sz = sz; // May be overridden by FRAME_OPT
if (to_recv != 0) {
self->state = FRAME_OPT;
} else {
if (frame_type >= FRAME_CLOSE) {
self->state = CONTROL;
} else {
self->state = PAYLOAD;
}
}
continue;
}
case FRAME_OPT: {
if ((self->buf_pos & 3) == 2) {
// First two bytes are message length
self->msg_sz = (self->buf[0] << 8) | self->buf[1];
}
if (self->buf_pos >= 4) {
// Last 4 bytes is mask
memcpy(self->mask, self->buf + self->buf_pos - 4, 4);
}
self->buf_pos = 0;
if ((self->last_flags & FRAME_OPCODE_MASK) >= FRAME_CLOSE) {
self->state = CONTROL;
} else {
self->state = PAYLOAD;
}
continue;
}
case PAYLOAD:
case CONTROL: {
mp_uint_t out_sz = 0;
if (self->msg_sz == 0) {
// In case message had zero payload
goto no_payload;
}
size_t sz = MIN(size, self->msg_sz);
out_sz = stream_p->read(self->sock, buf, sz, errcode);
if (out_sz == 0 || out_sz == MP_STREAM_ERROR) {
return out_sz;
}
sz = out_sz;
for (byte *p = buf; sz--; p++) {
*p ^= self->mask[self->mask_pos++ & 3];
}
self->msg_sz -= out_sz;
if (self->msg_sz == 0) {
byte last_state;
no_payload:
last_state = self->state;
self->state = FRAME_HEADER;
self->to_recv = 2;
self->mask_pos = 0;
self->buf_pos = 0;
// Handle control frame
if (last_state == CONTROL) {
byte frame_type = self->last_flags & FRAME_OPCODE_MASK;
if (frame_type == FRAME_CLOSE) {
static char close_resp[2] = {0x88, 0};
int err;
websocket_write(self_in, close_resp, sizeof(close_resp), &err);
return 0;
}
// DEBUG_printf("Finished receiving ctrl message %x, ignoring\n", self->last_flags);
continue;
}
}
if (out_sz != 0) {
return out_sz;
}
// Empty (data) frame received is not EOF
continue;
}
}
}
}
STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
assert(size < 0x10000);
byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)};
int hdr_sz;
if (size < 126) {
header[1] = size;
hdr_sz = 2;
} else {
header[1] = 126;
header[2] = size >> 8;
header[3] = size & 0xff;
hdr_sz = 4;
}
mp_obj_t dest[3];
if (self->opts & BLOCKING_WRITE) {
mp_load_method(self->sock, MP_QSTR_setblocking, dest);
dest[2] = mp_const_true;
mp_call_method_n_kw(1, 0, dest);
}
mp_uint_t out_sz = mp_stream_write_exactly(self->sock, header, hdr_sz, errcode);
if (*errcode == 0) {
out_sz = mp_stream_write_exactly(self->sock, buf, size, errcode);
}
if (self->opts & BLOCKING_WRITE) {
dest[2] = mp_const_false;
mp_call_method_n_kw(1, 0, dest);
}
if (*errcode != 0) {
return MP_STREAM_ERROR;
}
return out_sz;
}
STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
switch (request) {
case MP_STREAM_CLOSE:
// TODO: Send close signaling to the other side, otherwise it's
// abrupt close (connection abort).
mp_stream_close(self->sock);
return 0;
case MP_STREAM_GET_DATA_OPTS:
return self->ws_flags & FRAME_OPCODE_MASK;
case MP_STREAM_SET_DATA_OPTS: {
int cur = self->opts & FRAME_OPCODE_MASK;
self->opts = (self->opts & ~FRAME_OPCODE_MASK) | (arg & FRAME_OPCODE_MASK);
return cur;
}
default:
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
}
STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
};
STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table);
STATIC const mp_stream_p_t websocket_stream_p = {
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
.read = websocket_read,
.write = websocket_write,
.ioctl = websocket_ioctl,
};
STATIC const mp_obj_type_t websocket_type = {
{ &mp_type_type },
.name = MP_QSTR_websocket,
.make_new = websocket_make_new,
.protocol = &websocket_stream_p,
.locals_dict = (void *)&websocket_locals_dict,
};
STATIC const mp_rom_map_elem_t websocket_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_websocket) },
{ MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&websocket_type) },
};
STATIC MP_DEFINE_CONST_DICT(websocket_module_globals, websocket_module_globals_table);
const mp_obj_module_t mp_module_websocket = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&websocket_module_globals,
};
#endif // MICROPY_PY_WEBSOCKET

View File

@ -1,14 +0,0 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#ifndef MICROPY_INCLUDED_EXTMOD_MODWEBSOCKET_H
#define MICROPY_INCLUDED_EXTMOD_MODWEBSOCKET_H
#define FRAME_OPCODE_MASK 0x0f
enum {
FRAME_CONT, FRAME_TXT, FRAME_BIN,
FRAME_CLOSE = 0x8, FRAME_PING, FRAME_PONG
};
#endif // MICROPY_INCLUDED_EXTMOD_MODWEBSOCKET_H

@ -1 +1 @@
Subproject commit ef65415b5503ae71cc0a9064197f2e3fa5365d74
Subproject commit e3bf07cabb728ecfa2b78ea5e468179f94dbf933

View File

@ -11,6 +11,7 @@
#include "py/objtuple.h"
#include "py/objarray.h"
#include "py/stream.h"
#include "extmod/misc.h"
#include "lib/utils/interrupt_char.h"
#include "supervisor/shared/translate.h"
@ -39,6 +40,20 @@ int mp_uos_dupterm_rx_chr(void) {
continue;
}
#if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM
if (mp_uos_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) {
byte buf[1];
int errcode = 0;
const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
if (errcode == 0 && out_sz != 0) {
return buf[0];
} else {
continue;
}
}
#endif
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
byte buf[1];
@ -66,7 +81,7 @@ int mp_uos_dupterm_rx_chr(void) {
return buf[0];
}
} else {
mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
}
}
@ -79,12 +94,22 @@ void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
continue;
}
#if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM
if (mp_uos_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) {
int errcode = 0;
const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode);
continue;
}
#endif
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE);
nlr_pop();
} else {
mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
}
}
}

View File

@ -17,6 +17,10 @@
#include "extmod/vfs_fat.h"
#endif
#if defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX
#include "extmod/vfs_posix.h"
#endif
// For mp_vfs_proxy_call, the maximum number of additional args that can be passed.
// A fixed maximum size is used to avoid the need for a costly variable array.
#define PROXY_MAX_ARGS (2)
@ -203,7 +207,7 @@ mp_obj_t mp_vfs_umount(mp_obj_t mnt_in) {
mp_vfs_mount_t *vfs = NULL;
size_t mnt_len;
const char *mnt_str = NULL;
if (MP_OBJ_IS_STR(mnt_in)) {
if (mp_obj_is_str(mnt_in)) {
mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len);
}
for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) {
@ -244,6 +248,13 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
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);
#if defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX
// If the file is an integer then delegate straight to the POSIX handler
if (mp_obj_is_small_int(args[ARG_file].u_obj)) {
return mp_vfs_posix_file_open(&mp_type_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj);
}
#endif
mp_vfs_mount_t *vfs = lookup_path(args[ARG_file].u_obj, &args[ARG_file].u_obj);
return mp_vfs_proxy_call(vfs, MP_QSTR_open, 2, (mp_obj_t *)&args);
}

View File

@ -21,8 +21,8 @@
#include "supervisor/filesystem.h"
#include "supervisor/shared/translate.h"
#if _MAX_SS == _MIN_SS
#define SECSIZE(fs) (_MIN_SS)
#if FF_MAX_SS == FF_MIN_SS
#define SECSIZE(fs) (FF_MIN_SS)
#else
#define SECSIZE(fs) ((fs)->ssize)
#endif
@ -84,7 +84,7 @@ STATIC void verify_fs_writable(fs_user_mount_t *vfs) {
}
}
#if _FS_REENTRANT
#if FF_FS_REENTRANT
STATIC mp_obj_t fat_vfs_del(mp_obj_t self_in) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(self_in);
// f_umount only needs to be called to release the sync object
@ -99,8 +99,11 @@ STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {
fs_user_mount_t *vfs = MP_OBJ_TO_PTR(fat_vfs_make_new(&mp_fat_vfs_type, 1, &bdev_in, NULL));
// make the filesystem
uint8_t working_buf[_MAX_SS];
uint8_t working_buf[FF_MAX_SS];
FRESULT res = f_mkfs(&vfs->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
if (res == FR_MKFS_ABORTED) { // Probably doesn't support FAT16
res = f_mkfs(&vfs->fatfs, FM_FAT32, 0, working_buf, sizeof(working_buf));
}
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
@ -377,7 +380,7 @@ STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) {
t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree
t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail
t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags
t->items[9] = MP_OBJ_NEW_SMALL_INT(_MAX_LFN); // f_namemax
t->items[9] = MP_OBJ_NEW_SMALL_INT(FF_MAX_LFN); // f_namemax
return MP_OBJ_FROM_PTR(t);
}
@ -397,7 +400,7 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs
// check if we need to make the filesystem
FRESULT res = (self->flags & FSUSER_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK;
if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs)) {
uint8_t working_buf[_MAX_SS];
uint8_t working_buf[FF_MAX_SS];
res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
}
if (res != FR_OK) {
@ -451,7 +454,7 @@ STATIC const mp_obj_property_t fat_vfs_label_obj = {
#endif
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
#if _FS_REENTRANT
#if FF_FS_REENTRANT
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fat_vfs_del_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },

View File

@ -18,8 +18,8 @@
#include "lib/oofatfs/diskio.h"
#include "extmod/vfs_fat.h"
#if _MAX_SS == _MIN_SS
#define SECSIZE(fs) (_MIN_SS)
#if FF_MAX_SS == FF_MIN_SS
#define SECSIZE(fs) (FF_MIN_SS)
#else
#define SECSIZE(fs) ((fs)->ssize)
#endif
@ -34,7 +34,7 @@ STATIC fs_user_mount_t *disk_get_device(void *bdev) {
/*-----------------------------------------------------------------------*/
DRESULT disk_read(
bdev_t pdrv, /* Physical drive */
bdev_t pdrv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..128) */
@ -74,7 +74,7 @@ DRESULT disk_read(
/*-----------------------------------------------------------------------*/
DRESULT disk_write(
bdev_t pdrv, /* Physical drive */
bdev_t pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..128) */
@ -120,8 +120,8 @@ DRESULT disk_write(
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl(
bdev_t pdrv, /* Physical drive */
BYTE cmd, /* Control code */
bdev_t pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
) {
fs_user_mount_t *vfs = disk_get_device(pdrv);
@ -198,7 +198,7 @@ DRESULT disk_ioctl(
} else {
*((WORD *)buff) = out_value;
}
#if _MAX_SS != _MIN_SS
#if FF_MAX_SS != FF_MIN_SS
// need to store ssize because we use it in disk_read/disk_write
vfs->fatfs.ssize = *((WORD *)buff);
#endif

View File

@ -110,7 +110,7 @@ STATIC mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode
&& (strchr(mode, 'w') != NULL || strchr(mode, 'a') != NULL || strchr(mode, '+') != NULL)) {
mp_raise_OSError(MP_EROFS);
}
if (!MP_OBJ_IS_SMALL_INT(path_in)) {
if (!mp_obj_is_small_int(path_in)) {
path_in = vfs_posix_get_path_obj(self, path_in);
}
return mp_vfs_posix_file_open(&mp_type_textio, path_in, mode_in);
@ -172,6 +172,9 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
}
#ifdef _DIRENT_HAVE_D_TYPE
#ifdef DTTOIF
t->items[1] = MP_OBJ_NEW_SMALL_INT(DTTOIF(dirent->d_type));
#else
if (dirent->d_type == DT_DIR) {
t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
} else if (dirent->d_type == DT_REG) {
@ -179,10 +182,12 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
} else {
t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type);
}
#endif
#else
// DT_UNKNOWN should have 0 value on any reasonable system
t->items[1] = MP_OBJ_NEW_SMALL_INT(0);
#endif
#ifdef _DIRENT_HAVE_D_INO
t->items[2] = MP_OBJ_NEW_SMALL_INT(dirent->d_ino);
#else
@ -200,6 +205,9 @@ STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) {
iter->iternext = vfs_posix_ilistdir_it_iternext;
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
const char *path = vfs_posix_get_path_str(self, path_in);
if (path[0] == '\0') {
path = ".";
}
iter->dir = opendir(path);
if (iter->dir == NULL) {
mp_raise_OSError(errno);

View File

@ -74,7 +74,7 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_
mp_obj_t fid = file_in;
if (MP_OBJ_IS_SMALL_INT(fid)) {
if (mp_obj_is_small_int(fid)) {
o->fd = MP_OBJ_SMALL_INT_VALUE(fid);
return MP_OBJ_FROM_PTR(o);
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2016 Paul Sokolovsky
// SPDX-FileCopyrightText: Copyright (c) 2016 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT

@ -0,0 +1 @@
Subproject commit 669ab7b752d6c863577312560faf505656e5e603

@ -0,0 +1 @@
Subproject commit cdf99447307473080b2f2e95e7c3667247095ac0

View File

@ -30,12 +30,17 @@ typedef float float_t;
typedef union {
float f;
struct {
uint64_t m : 23;
uint64_t e : 8;
uint64_t s : 1;
uint32_t m : 23;
uint32_t e : 8;
uint32_t s : 1;
};
} float_s_t;
int __signbitf(float f) {
float_s_t u = {.f = f};
return u.s;
}
#ifndef NDEBUG
float copysignf(float x, float y) {
float_s_t fx={.f = x};
@ -55,10 +60,14 @@ static const float _M_LN2 = 0.6931472;
float log2f(float x) { return logf(x) / (float)_M_LN2; }
float tanhf(float x) {
if (isinf(x)) {
return copysignf(1, x);
int sign = 0;
if (x < 0) {
sign = 1;
x = -x;
}
return sinhf(x) / coshf(x);
x = expm1f(-2 * x);
x = x / (x + 2);
return sign ? x : -x;
}
/*****************************************************************************/

View File

@ -35,6 +35,10 @@
{
float y;
int local_signgam;
if (!isfinite(x)) {
/* special cases: tgammaf(nan)=nan, tgammaf(inf)=inf, tgammaf(-inf)=nan */
return x + INFINITY;
}
y = expf(__ieee754_lgammaf_r(x,&local_signgam));
if (local_signgam < 0) y = -y;
#ifdef _IEEE_LIBM

View File

@ -4,6 +4,10 @@ functions.
The files lgamma.c, log10.c and tanh.c are too small to have a meaningful
copyright or license.
The file copysign.c contains a double version of the float copysignf provided
in libm/math.c for use in DEBUG builds where the standard library copy is
not available.
The rest of the files in this directory are copied from the musl library,
v1.1.16, and, unless otherwise stated in the individual file, have the
following copyright and MIT license:

48
lib/libm_dbl/copysign.c Normal file
View File

@ -0,0 +1,48 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "libm.h"
#ifndef NDEBUG
typedef union {
double d;
struct {
uint64_t m : 52;
uint64_t e : 11;
uint64_t s : 1;
};
} double_s_t;
double copysign(double x, double y) {
double_s_t dx={.d = x};
double_s_t dy={.d = y};
// copy sign bit;
dx.s = dy.s;
return dx.d;
}
#endif

View File

@ -1,5 +1,12 @@
#include <math.h>
double tanh(double x) {
return sinh(x) / cosh(x);
int sign = 0;
if (x < 0) {
sign = 1;
x = -x;
}
x = expm1(-2 * x);
x = x / (x + 2);
return sign ? x : -x;
}

View File

@ -29,6 +29,10 @@
#define NETUTILS_IPV4ADDR_BUFSIZE 4
#define NETUTILS_TRACE_IS_TX (0x0001)
#define NETUTILS_TRACE_PAYLOAD (0x0002)
#define NETUTILS_TRACE_NEWLINE (0x0004)
typedef enum _netutils_endian_t {
NETUTILS_LITTLE,
NETUTILS_BIG,
@ -47,4 +51,6 @@ void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian
// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes).
mp_uint_t netutils_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian);
void netutils_ethernet_trace(const mp_print_t *print, size_t len, const uint8_t *buf, unsigned int flags);
#endif // MICROPY_INCLUDED_LIB_NETUTILS_NETUTILS_H

170
lib/netutils/trace.c Normal file
View File

@ -0,0 +1,170 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 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 "py/mphal.h"
#include "lib/netutils/netutils.h"
static uint32_t get_be16(const uint8_t *buf) {
return buf[0] << 8 | buf[1];
}
static uint32_t get_be32(const uint8_t *buf) {
return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
}
static void dump_hex_bytes(const mp_print_t *print, size_t len, const uint8_t *buf) {
for (size_t i = 0; i < len; ++i) {
mp_printf(print, " %02x", buf[i]);
}
}
static const char *ethertype_str(uint16_t type) {
// A value between 0x0000 - 0x05dc (inclusive) indicates a length, not type
switch (type) {
case 0x0800:
return "IPv4";
case 0x0806:
return "ARP";
case 0x86dd:
return "IPv6";
default:
return NULL;
}
}
void netutils_ethernet_trace(const mp_print_t *print, size_t len, const uint8_t *buf, unsigned int flags) {
mp_printf(print, "[% 8d] ETH%cX len=%u", mp_hal_ticks_ms(), flags & NETUTILS_TRACE_IS_TX ? 'T' : 'R', len);
mp_printf(print, " dst=%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
mp_printf(print, " src=%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
const char *ethertype = ethertype_str(buf[12] << 8 | buf[13]);
if (ethertype) {
mp_printf(print, " type=%s", ethertype);
} else {
mp_printf(print, " type=0x%04x", buf[12] << 8 | buf[13]);
}
if (len > 14) {
len -= 14;
buf += 14;
if (buf[-2] == 0x08 && buf[-1] == 0x00 && buf[0] == 0x45) {
// IPv4 packet
len = get_be16(buf + 2);
mp_printf(print, " srcip=%u.%u.%u.%u dstip=%u.%u.%u.%u",
buf[12], buf[13], buf[14], buf[15],
buf[16], buf[17], buf[18], buf[19]);
uint8_t prot = buf[9];
buf += 20;
len -= 20;
if (prot == 6) {
// TCP packet
uint16_t srcport = get_be16(buf);
uint16_t dstport = get_be16(buf + 2);
uint32_t seqnum = get_be32(buf + 4);
uint32_t acknum = get_be32(buf + 8);
uint16_t dataoff_flags = get_be16(buf + 12);
uint16_t winsz = get_be16(buf + 14);
mp_printf(print, " TCP srcport=%u dstport=%u seqnum=%u acknum=%u dataoff=%u flags=%x winsz=%u",
srcport, dstport, (unsigned)seqnum, (unsigned)acknum, dataoff_flags >> 12, dataoff_flags & 0x1ff, winsz);
buf += 20;
len -= 20;
if (dataoff_flags >> 12 > 5) {
mp_printf(print, " opts=");
size_t opts_len = ((dataoff_flags >> 12) - 5) * 4;
dump_hex_bytes(print, opts_len, buf);
buf += opts_len;
len -= opts_len;
}
} else if (prot == 17) {
// UDP packet
uint16_t srcport = get_be16(buf);
uint16_t dstport = get_be16(buf + 2);
mp_printf(print, " UDP srcport=%u dstport=%u", srcport, dstport);
len = get_be16(buf + 4);
buf += 8;
if ((srcport == 67 && dstport == 68) || (srcport == 68 && dstport == 67)) {
// DHCP
if (srcport == 67) {
mp_printf(print, " DHCPS");
} else {
mp_printf(print, " DHCPC");
}
dump_hex_bytes(print, 12 + 16 + 16 + 64, buf);
size_t n = 12 + 16 + 16 + 64 + 128;
len -= n;
buf += n;
mp_printf(print, " opts:");
switch (buf[6]) {
case 1:
mp_printf(print, " DISCOVER");
break;
case 2:
mp_printf(print, " OFFER");
break;
case 3:
mp_printf(print, " REQUEST");
break;
case 4:
mp_printf(print, " DECLINE");
break;
case 5:
mp_printf(print, " ACK");
break;
case 6:
mp_printf(print, " NACK");
break;
case 7:
mp_printf(print, " RELEASE");
break;
case 8:
mp_printf(print, " INFORM");
break;
}
}
} else {
// Non-UDP packet
mp_printf(print, " prot=%u", prot);
}
} else if (buf[-2] == 0x86 && buf[-1] == 0xdd && (buf[0] >> 4) == 6) {
// IPv6 packet
uint32_t h = get_be32(buf);
uint16_t l = get_be16(buf + 4);
mp_printf(print, " tclass=%u flow=%u len=%u nexthdr=%u hoplimit=%u", (unsigned)((h >> 20) & 0xff), (unsigned)(h & 0xfffff), l, buf[6], buf[7]);
mp_printf(print, " srcip=");
dump_hex_bytes(print, 16, buf + 8);
mp_printf(print, " dstip=");
dump_hex_bytes(print, 16, buf + 24);
buf += 40;
len -= 40;
}
if (flags & NETUTILS_TRACE_PAYLOAD) {
mp_printf(print, " data=");
dump_hex_bytes(print, len, buf);
}
}
if (flags & NETUTILS_TRACE_NEWLINE) {
mp_printf(print, "\n");
}
}

View File

@ -13,8 +13,6 @@
extern "C" {
#endif
/* Status of Disk Functions */
typedef BYTE DSTATUS;
@ -47,11 +45,11 @@ DRESULT disk_ioctl (void *drv, BYTE cmd, void* buff);
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
#define IOCTL_INIT 5
#define IOCTL_STATUS 6

File diff suppressed because it is too large Load Diff

View File

@ -3,10 +3,10 @@
*/
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT file system module R0.12b /
/ FatFs - Generic FAT Filesystem module R0.13c /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2016, ChaN, all right reserved.
/ Copyright (C) 2018, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@ -19,81 +19,93 @@
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 68020 /* Revision ID */
#ifndef FF_DEFINED
#define FF_DEFINED 86604 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include FFCONF_H /* FatFs configuration options */
/* This type MUST be 8-bit */
typedef uint8_t BYTE;
/* These types MUST be 16-bit */
typedef int16_t SHORT;
typedef uint16_t WORD;
typedef uint16_t WCHAR;
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* These types MUST be 32-bit */
typedef int32_t LONG;
typedef uint32_t DWORD;
/* This type MUST be 64-bit (Remove this for C89 compatibility) */
typedef uint64_t QWORD;
#include FFCONF_H /* FatFs configuration options */
#if _FATFS != _FFCONF
#if FF_DEFINED != FFCONF_DEF
#error Wrong configuration file (ffconf.h).
#endif
/* Integer types used for FatFs API */
#if defined(_WIN32) /* Main development platform */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
#define FF_INTDEF 2
#include <stdint.h>
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint16_t WCHAR; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
#else /* Earlier than C99 */
#define FF_INTDEF 1
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef unsigned short WORD; /* 16-bit unsigned integer */
typedef unsigned short WCHAR; /* 16-bit unsigned integer */
typedef unsigned long DWORD; /* 32-bit unsigned integer */
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PT(fs) (fs->part) /* Get partition index */
#else /* Single partition configuration */
#define LD2PT(fs) 0 /* Find first valid partition or in SFD */
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode (UTF-16) string */
#if _USE_LFN == 0
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U ## x
#define _TEXT(x) U ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size variables */
#if _FS_EXFAT
#if _USE_LFN == 0
#error LFN must be enabled when enable exFAT
#if FF_FS_EXFAT
#if FF_INTDEF != 2
#error exFAT feature wants C99 or later
#endif
typedef QWORD FSIZE_t;
#else
@ -102,39 +114,39 @@ typedef DWORD FSIZE_t;
/* File system object structure (FATFS) */
/* Filesystem object structure (FATFS) */
typedef struct {
void *drv; // block device underlying this filesystem
#if _MULTI_PARTITION /* Multiple partition configuration */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
BYTE part; // Partition: 0:Auto detect, 1-4:Forced partition
#endif
BYTE fs_type; /* File system type (0:N/A) */
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* File system mount ID */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if _MAX_SS != _MIN_SS
#if FF_MAX_SS != FF_MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if _USE_LFN != 0
#if FF_USE_LFN
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if _FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer */
#if FF_FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if _FS_RPATH != 0
#if FF_FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#if _FS_EXFAT
#if FF_FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
@ -146,52 +158,56 @@ typedef struct {
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
#if FF_FS_EXFAT
DWORD bitbase; /* Allocation bitmap base sector */
#endif
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (_FDID) */
/* Object ID and allocation information (FFOBJID) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:got flagmented, b2:sub-directory stretched) */
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if _FS_EXFAT
DWORD n_cont; /* Size of coutiguous part, clusters - 1 (valid when stat == 3) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0) */
FATFS* fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if FF_FS_EXFAT
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */
#endif
#if _FS_LOCK != 0
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#if FF_FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} _FDID;
} FFOBJID;
/* File object structure (FIL) */
typedef struct {
_FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fprt is 0) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#if !FF_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
#endif
#if _USE_FASTSEEK
#if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
@ -200,16 +216,16 @@ typedef struct {
/* Directory object structure (FF_DIR) */
typedef struct {
_FDID obj; /* Object identifier */
FFOBJID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
DWORD sect; /* Current sector (0:Read operation has terminated) */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if _USE_LFN != 0
#if FF_USE_LFN
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if _USE_FIND
#if FF_USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} FF_DIR;
@ -223,11 +239,11 @@ typedef struct {
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if _USE_LFN != 0
TCHAR altname[13]; /* Altenative file name */
TCHAR fname[_MAX_LFN + 1]; /* Primary file name */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[13]; /* File name */
TCHAR fname[12 + 1]; /* File name */
#endif
} FILINFO;
@ -254,7 +270,7 @@ typedef enum {
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
@ -292,6 +308,7 @@ FRESULT f_mount (FATFS* fs); /* Mount/Unm
FRESULT f_umount (FATFS* fs); /* Unmount a logical drive */
FRESULT f_mkfs (FATFS *fs, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (void *pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
FRESULT f_setcp (WORD cp); /* Set current code page */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
@ -299,6 +316,8 @@ FRESULT f_fdisk (void *pdrv, const DWORD* szt, void* work); /* Divide a
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
@ -311,26 +330,27 @@ FRESULT f_fdisk (void *pdrv, const DWORD* szt, void* work); /* Divide a
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY && !_FS_NORTC
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN != 0 /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
#endif
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (FATFS *fatfs, _SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#if FF_FS_REENTRANT
int ff_cre_syncobj (FATFS *fatfs, FF_SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#endif
@ -377,4 +397,4 @@ int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
}
#endif
#endif /* _FATFS */
#endif /* FF_DEFINED */

View File

@ -2,11 +2,11 @@
* This file is part of the MicroPython project, http://micropython.org/
*
* Original file from:
* FatFs - FAT file system module configuration file R0.12a (C)ChaN, 2016
* FatFs - FAT file system module configuration file R0.13c (C)ChaN, 2018
*
* The MIT License (MIT)
*
* SPDX-FileCopyrightText: Copyright (c) 2013-2017 Damien P. George
* SPDX-FileCopyrightText: Copyright (c) 2013-2019 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
@ -30,73 +30,72 @@
#include "py/mpconfig.h"
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file
/ FatFs Functional Configurations
/---------------------------------------------------------------------------*/
#define _FFCONF 68020 /* Revision ID */
#define FFCONF_DEF 86604 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define _FS_READONLY 0
#define FF_FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define _FS_MINIMIZE 0
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
/ 0: Basic functions are fully enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define _USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
#define FF_USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define _USE_FIND 0
#define FF_USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define _USE_MKFS 1
#define FF_USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define _USE_FASTSEEK 1
#define FF_USE_FASTSEEK 1
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define _USE_EXPAND 0
#define FF_USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define _USE_CHMOD 1
#define FF_USE_CHMOD 1
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
#ifdef MICROPY_FATFS_USE_LABEL
#define _USE_LABEL (MICROPY_FATFS_USE_LABEL)
#define FF_USE_LABEL (MICROPY_FATFS_USE_LABEL)
#else
#define _USE_LABEL 0
#define FF_USE_LABEL 0
#endif
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define _USE_FORWARD 0
#define FF_USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
@ -105,14 +104,13 @@
/---------------------------------------------------------------------------*/
#ifdef MICROPY_FATFS_LFN_CODE_PAGE
#define _CODE_PAGE (MICROPY_FATFS_LFN_CODE_PAGE)
#define FF_CODE_PAGE MICROPY_FATFS_LFN_CODE_PAGE
#else
#define _CODE_PAGE 1
#define FF_CODE_PAGE 437
#endif
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/ Incorrect code page setting can cause a file open failure.
/
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
@ -134,59 +132,77 @@
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
/ 0 - Include all code pages above and configured by f_setcp()
*/
#ifdef MICROPY_FATFS_ENABLE_LFN
#define _USE_LFN (MICROPY_FATFS_ENABLE_LFN)
#define FF_USE_LFN (MICROPY_FATFS_ENABLE_LFN)
#else
#define _USE_LFN 0
#define FF_USE_LFN 0
#endif
#ifdef MICROPY_FATFS_MAX_LFN
#define _MAX_LFN (MICROPY_FATFS_MAX_LFN)
#define FF_MAX_LFN (MICROPY_FATFS_MAX_LFN)
#else
#define _MAX_LFN 255
#define FF_MAX_LFN 255
#endif
/* The _USE_LFN switches the support of long file name (LFN).
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable support of LFN. _MAX_LFN has no effect.
/ 0: Disable LFN. FF_MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
/ It should be set 255 to support full featured LFN operations.
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
/ specification.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree(), must be added to the project. */
/ ff_memfree() in ffsystem.c, need to be added to the project. */
#define _LFN_UNICODE 0
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
/ This option also affects behavior of string I/O functions. */
#define _STRF_ENCODE 3
/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
#define FF_LFN_UNICODE 0
/* This option switches the character encoding on the API when LFN is enabled.
/
/ 0: ANSI/OEM
/ 1: UTF-16LE
/ 2: UTF-16BE
/ 3: UTF-8
/ 0: ANSI/OEM in current CP (TCHAR = char)
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
/ 2: Unicode in UTF-8 (TCHAR = char)
/ 3: Unicode in UTF-32 (TCHAR = DWORD)
/
/ This option has no effect when _LFN_UNICODE == 0. */
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO structure
/ which is used to read out directory items. These values should be suffcient for
/ the file names to read. The maximum possible length of the read file name depends
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_STRF_ENCODE 3
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#ifdef MICROPY_FATFS_RPATH
#define _FS_RPATH (MICROPY_FATFS_RPATH)
#define FF_FS_RPATH (MICROPY_FATFS_RPATH)
#else
#define _FS_RPATH 0
#define FF_FS_RPATH 0
#endif
/* This option configures support of relative path.
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
@ -198,53 +214,58 @@
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
#define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */
#define _STR_VOLUME_ID 0
#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* _STR_VOLUME_ID switches string support of volume ID.
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
#define FF_STR_VOLUME_ID 0
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/ not defined, a user defined volume string table needs to be defined as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/
#ifdef MICROPY_FATFS_MULTI_PARTITION
#define _MULTI_PARTITION (MICROPY_FATFS_MULTI_PARTITION)
#define FF_MULTI_PARTITION (MICROPY_FATFS_MULTI_PARTITION)
#else
#define _MULTI_PARTITION 0
#define FF_MULTI_PARTITION 0
#endif
/* This option switches support of multi-partition on a physical drive.
/* This option switches support for multiple volumes on the physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When multi-partition is enabled (1), each logical drive number can be bound to
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
#define _MIN_SS 512
#define FF_MIN_SS 512
#ifdef MICROPY_FATFS_MAX_SS
#define _MAX_SS (MICROPY_FATFS_MAX_SS)
#define FF_MAX_SS (MICROPY_FATFS_MAX_SS)
#else
#define _MAX_SS 512
#define FF_MAX_SS 512
#endif
/* These options configure the range of sector size to be supported. (512, 1024,
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
/ disk_ioctl() function. */
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
#define _USE_TRIM 0
/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
#define FF_USE_TRIM 0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define _FS_NOFSINFO 0
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
@ -261,44 +282,44 @@
/ System Configurations
/---------------------------------------------------------------------------*/
#define _FS_TINY 1
#define FF_FS_TINY 1
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the file system object (FATFS) is used for the file data transfer. */
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#ifdef MICROPY_FATFS_EXFAT
#define _FS_EXFAT (MICROPY_FATFS_EXFAT)
#define FF_FS_EXFAT (MICROPY_FATFS_EXFAT)
#else
#define _FS_EXFAT 0
#define FF_FS_EXFAT 0
#endif
/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
/ Note that enabling exFAT discards C89 compatibility. */
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#ifdef MICROPY_FATFS_NORTC
#define _FS_NORTC (MICROPY_FATFS_NORTC)
#define FF_FS_NORTC (MICROPY_FATFS_NORTC)
#else
#define _FS_NORTC 0
#define FF_FS_NORTC 0
#endif
#define _NORTC_MON 1
#define _NORTC_MDAY 1
#define _NORTC_YEAR 2016
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to get current time form real-time clock. _NORTC_MON,
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2018
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */
#define _FS_LOCK 0
/* The option _FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
#define FF_FS_LOCK 0
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
@ -309,41 +330,40 @@
#ifdef MICROPY_FATFS_REENTRANT
#define _FS_REENTRANT (MICROPY_FATFS_REENTRANT)
#define FF_FS_REENTRANT (MICROPY_FATFS_REENTRANT)
#else
#define _FS_REENTRANT 0
#define FF_FS_REENTRANT 0
#endif
// milliseconds
#ifdef MICROPY_FATFS_TIMEOUT
#define _FS_TIMEOUT (MICROPY_FATFS_TIMEOUT)
#define FF_FS_TIMEOUT (MICROPY_FATFS_TIMEOUT)
#else
#define _FS_TIMEOUT 1000
#define FF_FS_TIMEOUT 1000
#endif
#ifdef MICROPY_FATFS_SYNC_T
#define _SYNC_t MICROPY_FATFS_SYNC_T
#define FF_SYNC_t MICROPY_FATFS_SYNC_T
#else
#define _SYNC_t HANDLE
#define FF_SYNC_t HANDLE
#endif
/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/* #include <windows.h> // O/S definitions */
/*--- End of configuration options ---*/

View File

@ -1,33 +1,46 @@
/*------------------------------------------------------------------------*/
/* Unicode - Local code bidirectional converter (C)ChaN, 2015 */
/* (SBCS code pages) */
/* Unicode handling functions for FatFs R0.13c */
/*------------------------------------------------------------------------*/
/* 437 U.S.
/ 720 Arabic
/ 737 Greek
/ 771 KBL
/ 775 Baltic
/ 850 Latin 1
/ 852 Latin 2
/ 855 Cyrillic
/ 857 Turkish
/ 860 Portuguese
/ 861 Icelandic
/ 862 Hebrew
/ 863 Canadian French
/ 864 Arabic
/ 865 Nordic
/ 866 Russian
/ 869 Greek 2
/* This module will occupy a huge memory in the .const section when the /
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
/ utilitiy for the code conversion, this module should be modified to use /
/ that function to avoid silly memory consumption. /
/-------------------------------------------------------------------------*/
/*
/ Copyright (C) 2018, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
*/
#include "../ff.h"
#include "ff.h"
#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */
#if FF_DEFINED != 86604 /* Revision ID */
#error Wrong include file (ff.h).
#endif
#define MERGE2(a, b) a ## b
#define CVTBL(tbl, cp) MERGE2(tbl, cp)
#if _CODE_PAGE == 437
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
/*------------------------------------------------------------------------*/
/* Code Conversion Tables */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0
static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -37,11 +50,9 @@ const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 720
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0
static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
@ -51,11 +62,9 @@ const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 737
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0
static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
@ -65,11 +74,9 @@ const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 771
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP771(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0
static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
@ -79,11 +86,9 @@ const WCHAR Tbl[] = { /* CP771(0x80-0xFF) to Unicode conversion table */
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 775
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0
static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
@ -93,11 +98,9 @@ const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 850
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0
static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -107,11 +110,9 @@ const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 852
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0
static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
@ -121,11 +122,9 @@ const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 855
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0
static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
@ -135,11 +134,9 @@ const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 857
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0
static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -149,11 +146,9 @@ const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 860
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP860(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0
static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -163,11 +158,9 @@ const WCHAR Tbl[] = { /* CP860(0x80-0xFF) to Unicode conversion table */
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 861
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP861(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0
static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -177,11 +170,9 @@ const WCHAR Tbl[] = { /* CP861(0x80-0xFF) to Unicode conversion table */
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 862
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0
static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -191,11 +182,9 @@ const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 863
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP863(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0
static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
@ -205,11 +194,9 @@ const WCHAR Tbl[] = { /* CP863(0x80-0xFF) to Unicode conversion table */
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 864
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP864(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0
static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
@ -219,11 +206,9 @@ const WCHAR Tbl[] = { /* CP864(0x80-0xFF) to Unicode conversion table */
0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1,
0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000
};
#elif _CODE_PAGE == 865
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP865(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0
static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
@ -233,11 +218,9 @@ const WCHAR Tbl[] = { /* CP865(0x80-0xFF) to Unicode conversion table */
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 866
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0
static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
@ -247,11 +230,9 @@ const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 869
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP869(0x80-0xFF) to Unicode conversion table */
#endif
#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0
static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
@ -261,36 +242,32 @@ const WCHAR Tbl[] = { /* CP869(0x80-0xFF) to Unicode conversion table */
0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384,
0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0
};
#endif
#if !_TBLDEF || !_USE_LFN
#error This file is not needed at current configuration. Remove from the project.
#endif
WCHAR ff_convert ( /* Converted character, Returns zero on error */
WCHAR chr, /* Character code to be converted */
UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* SBCS fixed code page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
WCHAR c;
WCHAR c = 0;
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
if (chr < 0x80) { /* ASCII */
c = chr;
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else {
if (dir) { /* OEM code to Unicode */
c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80];
} else { /* Unicode to OEM code */
for (c = 0; c < 0x80; c++) {
if (chr == Tbl[c]) break;
}
} else { /* Non-ASCII */
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
for (c = 0; c < 0x80 && uni != p[c]; c++) ;
c = (c + 0x80) & 0xFF;
}
}
@ -298,56 +275,314 @@ WCHAR ff_convert ( /* Converted character, Returns zero on error */
return c;
}
WCHAR ff_wtoupper ( /* Returns upper converted character */
WCHAR chr /* Unicode character to be upper converted (BMP only) */
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR oem, /* OEM code to be converted */
WORD cp /* Code page for the conversion */
)
{
/* Compressed upper conversion table */
static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */
WCHAR c = 0;
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
if (oem < 0x100) c = p[oem - 0x80];
}
}
return c;
}
#endif
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* DBCS fixed code page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE >= 900
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0, uc;
UINT i = 0, n, li, hi;
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else { /* Non-ASCII */
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
uc = (WCHAR)uni;
p = CVTBL(uni2oem, FF_CODE_PAGE);
hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1;
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (uc == p[i * 2]) break;
if (uc > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR oem, /* OEM code to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0;
UINT i = 0, n, li, hi;
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
if (cp == FF_CODE_PAGE) { /* Is it valid code page? */
p = CVTBL(oem2uni, FF_CODE_PAGE);
hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1;
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (oem == p[i * 2]) break;
if (oem > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
}
return c;
}
#endif
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for dynamic code page configuration */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 0
static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0};
static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0};
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0, uc;
UINT i, n, li, hi;
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else { /* Non-ASCII */
if (uni < 0x10000) { /* Is it in BMP? */
uc = (WCHAR)uni;
p = 0;
if (cp < 900) { /* SBCS */
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */
p = cp_table[i];
if (p) { /* Is it valid code page ? */
for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */
c = (c + 0x80) & 0xFF;
}
} else { /* DBCS */
switch (cp) { /* Get conversion table */
case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break;
case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break;
case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break;
case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break;
}
if (p) { /* Is it valid code page? */
li = 0;
for (n = 16; n; n--) { /* Find OEM code */
i = li + (hi - li) / 2;
if (uc == p[i * 2]) break;
if (uc > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
}
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0;
UINT i, n, li, hi;
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
p = 0;
if (cp < 900) { /* SBCS */
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */
p = cp_table[i];
if (p) { /* Is it a valid CP ? */
if (oem < 0x100) c = p[oem - 0x80];
}
} else { /* DBCS */
switch (cp) {
case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break;
case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break;
case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break;
case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break;
}
if (p) {
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (oem == p[i * 2]) break;
if (oem > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
}
}
return c;
}
#endif
/*------------------------------------------------------------------------*/
/* Unicode up-case conversion */
/*------------------------------------------------------------------------*/
DWORD ff_wtoupper ( /* Returns up-converted code point */
DWORD uni /* Unicode code point to be up-converted */
)
{
const WORD *p;
WORD uc, bc, nc, cmd;
static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */
/* Basic Latin */
0x0061,0x031A,
/* Latin-1 Supplement */
0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178,
0x00E0,0x0317,
0x00F8,0x0307,
0x00FF,0x0001,0x0178,
/* Latin Extended-A */
0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106,
0x0100,0x0130,
0x0132,0x0106,
0x0139,0x0110,
0x014A,0x012E,
0x0179,0x0106,
/* Latin Extended-B */
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128,
0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A,
0x01CD,0x0110,
0x01DD,0x0001,0x018E,
0x01DE,0x0112,
0x01F3,0x0003,0x01F1,0x01F4,0x01F4,
0x01F8,0x0128,
0x0222,0x0112,
0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241,
0x0246,0x010A,
/* IPA Extensions */
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
/* Greek, Coptic */
0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311,
0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118,
0x037B,0x0003,0x03FD,0x03FE,0x03FF,
0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A,
0x03B1,0x0311,
0x03C2,0x0002,0x03A3,0x03A3,
0x03C4,0x0308,
0x03CC,0x0003,0x038C,0x038E,0x038F,
0x03D8,0x0118,
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
/* Cyrillic */
0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144,
0x0430,0x0320,
0x0450,0x0710,
0x0460,0x0122,
0x048A,0x0136,
0x04C1,0x010E,
0x04CF,0x0001,0x04C0,
0x04D0,0x0144,
/* Armenian */
0x0561,0x0426,
0x0000
0x0000 /* EOT */
};
static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */
static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */
/* Phonetic Extensions */
0x1D7D,0x0001,0x2C63,
/* Latin Extended Additional */
0x1E00,0x0196, 0x1EA0,0x015A,
0x1E00,0x0196,
0x1EA0,0x015A,
/* Greek Extended */
0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606,
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608,
0x1F00,0x0608,
0x1F10,0x0606,
0x1F20,0x0608,
0x1F30,0x0608,
0x1F40,0x0606,
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F,
0x1F60,0x0608,
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF2,0x0001,0x1FFC,
0x1F80,0x0608,
0x1F90,0x0608,
0x1FA0,0x0608,
0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
0x1FCC,0x0001,0x1FC3,
0x1FD0,0x0602,
0x1FE0,0x0602,
0x1FE5,0x0001,0x1FEC,
0x1FF3,0x0001,0x1FFC,
/* Letterlike Symbols */
0x214E,0x0001,0x2132,
/* Number forms */
0x2170,0x0210, 0x2184,0x0001,0x2183,
0x2170,0x0210,
0x2184,0x0001,0x2183,
/* Enclosed Alphanumerics */
0x24D0,0x051A, 0x2C30,0x042F,
0x24D0,0x051A,
0x2C30,0x042F,
/* Latin Extended-C */
0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102,
0x2C60,0x0102,
0x2C67,0x0106, 0x2C75,0x0102,
/* Coptic */
0x2C80,0x0164,
/* Georgian Supplement */
@ -355,33 +590,38 @@ WCHAR ff_wtoupper ( /* Returns upper converted character */
/* Full-width */
0xFF41,0x031A,
0x0000
0x0000 /* EOT */
};
const WCHAR *p;
WCHAR bc, nc, cmd;
p = chr < 0x1000 ? cvt1 : cvt2;
for (;;) {
bc = *p++; /* Get block base */
if (!bc || chr < bc) break;
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
if (chr < bc + nc) { /* In the block? */
switch (cmd) {
case 0: chr = p[chr - bc]; break; /* Table conversion */
case 1: chr -= (chr - bc) & 1; break; /* Case pairs */
case 2: chr -= 16; break; /* Shift -16 */
case 3: chr -= 32; break; /* Shift -32 */
case 4: chr -= 48; break; /* Shift -48 */
case 5: chr -= 26; break; /* Shift -26 */
case 6: chr += 8; break; /* Shift +8 */
case 7: chr -= 80; break; /* Shift -80 */
case 8: chr -= 0x1C60; break; /* Shift -0x1C60 */
if (uni < 0x10000) { /* Is it in BMP? */
uc = (WORD)uni;
p = uc < 0x1000 ? cvt1 : cvt2;
for (;;) {
bc = *p++; /* Get the block base */
if (bc == 0 || uc < bc) break; /* Not matched? */
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
if (uc < bc + nc) { /* In the block? */
switch (cmd) {
case 0: uc = p[uc - bc]; break; /* Table conversion */
case 1: uc -= (uc - bc) & 1; break; /* Case pairs */
case 2: uc -= 16; break; /* Shift -16 */
case 3: uc -= 32; break; /* Shift -32 */
case 4: uc -= 48; break; /* Shift -48 */
case 5: uc -= 26; break; /* Shift -26 */
case 6: uc += 8; break; /* Shift +8 */
case 7: uc -= 80; break; /* Shift -80 */
case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */
}
break;
}
break;
if (cmd == 0) p += nc; /* Skip table if needed */
}
if (!cmd) p += nc;
uni = uc;
}
return chr;
return uni;
}
#endif /* #if FF_USE_LFN */

View File

@ -1,17 +0,0 @@
#include "../ff.h"
#if _USE_LFN != 0
#if _CODE_PAGE == 932 /* Japanese Shift_JIS */
#include "cc932.c"
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
#include "cc936.c"
#elif _CODE_PAGE == 949 /* Korean */
#include "cc949.c"
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
#include "cc950.c"
#else /* Single Byte Character-Set */
#include "ccsbcs.c"
#endif
#endif

@ -1 +1 @@
Subproject commit c2c81ded118484f8925bf81e270b416739cd72d9
Subproject commit 98017c57349e259fab70c6a7830436b19a55f6f4

34
lib/utils/gchelper.h Normal file
View File

@ -0,0 +1,34 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_LIB_UTILS_GCHELPER_H
#define MICROPY_INCLUDED_LIB_UTILS_GCHELPER_H
#include <stdint.h>
uintptr_t gc_helper_get_sp(void);
uintptr_t gc_helper_get_regs_and_sp(uintptr_t *regs);
#endif // MICROPY_INCLUDED_LIB_UTILS_GCHELPER_H

View File

@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* SPDX-FileCopyrightText: Copyright (c) 2017-2018 Damien P. George
* Copyright (c) 2018 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
@ -23,35 +23,39 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H
#define MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H
#include "py/mphal.h"
.syntax unified
.cpu cortex-m0
.thumb
enum {
MP_QSPI_IOCTL_INIT,
MP_QSPI_IOCTL_DEINIT,
MP_QSPI_IOCTL_BUS_ACQUIRE,
MP_QSPI_IOCTL_BUS_RELEASE,
};
.section .text
.align 2
typedef struct _mp_qspi_proto_t {
int (*ioctl)(void *self, uint32_t cmd);
void (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data);
void (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src);
uint32_t (*read_cmd)(void *self, uint8_t cmd, size_t len);
void (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest);
} mp_qspi_proto_t;
.global gc_helper_get_regs_and_sp
.type gc_helper_get_regs_and_sp, %function
typedef struct _mp_soft_qspi_obj_t {
mp_hal_pin_obj_t cs;
mp_hal_pin_obj_t clk;
mp_hal_pin_obj_t io0;
mp_hal_pin_obj_t io1;
mp_hal_pin_obj_t io2;
mp_hal_pin_obj_t io3;
} mp_soft_qspi_obj_t;
@ uint gc_helper_get_regs_and_sp(r0=uint regs[10])
gc_helper_get_regs_and_sp:
@ store registers into given array
str r4, [r0, #0]
str r5, [r0, #4]
str r6, [r0, #8]
str r7, [r0, #12]
mov r1, r8
str r1, [r0, #16]
mov r1, r9
str r1, [r0, #20]
mov r1, r10
str r1, [r0, #24]
mov r1, r11
str r1, [r0, #28]
mov r1, r12
str r1, [r0, #32]
mov r1, r13
str r1, [r0, #36]
extern const mp_qspi_proto_t mp_soft_qspi_proto;
@ return the sp
mov r0, sp
bx lr
#endif // MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H
.size gc_helper_get_regs_and_sp, .-gc_helper_get_regs_and_sp

67
lib/utils/gchelper_m3.s Normal file
View File

@ -0,0 +1,67 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
.syntax unified
.cpu cortex-m3
.thumb
.section .text
.align 2
.global gc_helper_get_sp
.type gc_helper_get_sp, %function
@ uint gc_helper_get_sp(void)
gc_helper_get_sp:
@ return the sp
mov r0, sp
bx lr
.size gc_helper_get_sp, .-gc_helper_get_sp
.global gc_helper_get_regs_and_sp
.type gc_helper_get_regs_and_sp, %function
@ uint gc_helper_get_regs_and_sp(r0=uint regs[10])
gc_helper_get_regs_and_sp:
@ store registers into given array
str r4, [r0], #4
str r5, [r0], #4
str r6, [r0], #4
str r7, [r0], #4
str r8, [r0], #4
str r9, [r0], #4
str r10, [r0], #4
str r11, [r0], #4
str r12, [r0], #4
str r13, [r0], #4
@ return the sp
mov r0, sp
bx lr
.size gc_helper_get_regs_and_sp, .-gc_helper_get_regs_and_sp

View File

@ -29,7 +29,7 @@
#if MICROPY_KBD_EXCEPTION
int mp_interrupt_char;
int mp_interrupt_char = -1;
void mp_hal_set_interrupt_char(int c) {
if (c != -1) {

124
lib/utils/mpirq.c Normal file
View File

@ -0,0 +1,124 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Daniel Campora
* 2018 Tobias Badertscher
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include "py/runtime.h"
#include "py/gc.h"
#include "lib/utils/mpirq.h"
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
const mp_arg_t mp_irq_init_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
};
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent) {
mp_irq_obj_t *self = m_new0(mp_irq_obj_t, 1);
self->base.type = &mp_irq_type;
self->methods = (mp_irq_methods_t *)methods;
self->parent = parent;
self->handler = mp_const_none;
self->ishard = false;
return self;
}
void mp_irq_handler(mp_irq_obj_t *self) {
if (self->handler != mp_const_none) {
if (self->ishard) {
// When executing code within a handler we must lock the GC to prevent
// any memory allocations.
gc_lock();
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_call_function_1(self->handler, self->parent);
nlr_pop();
} else {
// Uncaught exception; disable the callback so that it doesn't run again
self->methods->trigger(self->parent, 0);
self->handler = mp_const_none;
printf("Uncaught exception in IRQ callback handler\n");
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
}
gc_unlock();
} else {
// Schedule call to user function
mp_sched_schedule(self->handler, self->parent);
}
}
}
/******************************************************************************/
// MicroPython bindings
STATIC mp_obj_t mp_irq_flags(mp_obj_t self_in) {
mp_irq_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_FLAGS));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags);
STATIC mp_obj_t mp_irq_trigger(size_t n_args, const mp_obj_t *args) {
mp_irq_obj_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_t ret_obj = mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_TRIGGERS));
if (n_args == 2) {
// Set trigger
self->methods->trigger(self->parent, mp_obj_get_int(args[1]));
}
return ret_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_irq_trigger_obj, 1, 2, mp_irq_trigger);
STATIC mp_obj_t mp_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 0, false);
mp_irq_handler(MP_OBJ_TO_PTR(self_in));
return mp_const_none;
}
STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_flags), MP_ROM_PTR(&mp_irq_flags_obj) },
{ MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&mp_irq_trigger_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table);
const mp_obj_type_t mp_irq_type = {
{ &mp_type_type },
.name = MP_QSTR_irq,
.call = mp_irq_call,
.locals_dict = (mp_obj_dict_t *)&mp_irq_locals_dict,
};

82
lib/utils/mpirq.h Normal file
View File

@ -0,0 +1,82 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Daniel Campora
*
* 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_LIB_UTILS_MPIRQ_H
#define MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
enum {
MP_IRQ_ARG_INIT_handler = 0,
MP_IRQ_ARG_INIT_trigger,
MP_IRQ_ARG_INIT_hard,
MP_IRQ_ARG_INIT_NUM_ARGS,
};
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef mp_obj_t (*mp_irq_init_t)(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
typedef mp_uint_t (*mp_irq_uint_method_one_uint_para_t)(mp_obj_t self, mp_uint_t trigger);
typedef mp_uint_t (*mp_irq_int_method_one_para_t)(mp_obj_t self, mp_uint_t info_type);
enum {
MP_IRQ_INFO_FLAGS,
MP_IRQ_INFO_TRIGGERS,
MP_IRQ_INFO_CNT
};
typedef struct _mp_irq_methods_t {
mp_irq_init_t init;
mp_irq_uint_method_one_uint_para_t trigger;
mp_irq_int_method_one_para_t info;
} mp_irq_methods_t;
typedef struct _mp_irq_obj_t {
mp_obj_base_t base;
mp_irq_methods_t *methods;
mp_obj_t parent;
mp_obj_t handler;
bool ishard;
} mp_irq_obj_t;
/******************************************************************************
DECLARE EXPORTED DATA
******************************************************************************/
extern const mp_arg_t mp_irq_init_args[];
extern const mp_obj_type_t mp_irq_type;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent);
void mp_irq_handler(mp_irq_obj_t *self);
#endif // MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H

View File

@ -26,8 +26,6 @@
#include "py/mpconfig.h"
#if MICROPY_USE_INTERNAL_PRINTF
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
@ -39,6 +37,18 @@
#include "py/formatfloat.h"
#endif
#if MICROPY_DEBUG_PRINTERS
int DEBUG_printf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = mp_vprintf(MICROPY_DEBUG_PRINTER, fmt, ap);
va_end(ap);
return ret;
}
#endif
#if MICROPY_USE_INTERNAL_PRINTF
#undef putchar // Some stdlibs have a #define for putchar
int printf(const char *fmt, ...);
int vprintf(const char *fmt, va_list ap);
@ -59,20 +69,6 @@ int vprintf(const char *fmt, va_list ap) {
return mp_vprintf(&mp_plat_print, fmt, ap);
}
#if MICROPY_DEBUG_PRINTERS
extern const mp_print_t MICROPY_DEBUG_PRINTER_DEST;
int DEBUG_printf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
#ifndef MICROPY_DEBUG_PRINTER_DEST
#define MICROPY_DEBUG_PRINTER_DEST mp_plat_print
#endif
int ret = mp_vprintf(&MICROPY_DEBUG_PRINTER_DEST, fmt, ap);
va_end(ap);
return ret;
}
#endif
// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a')
int putchar(int c) {
char chr = c;

View File

@ -129,7 +129,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
mp_hal_stdout_tx_strn("\x04", 1);
}
// check for SystemExit
if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) {
if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {
// at the moment, the value of SystemExit is unused
ret = pyexec_system_exit;
#if CIRCUITPY_ALARM
@ -138,7 +138,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
#endif
} else {
if ((mp_obj_t)nlr.ret_val != MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
}
ret = PYEXEC_EXCEPTION;
}
@ -197,6 +197,7 @@ typedef struct _repl_t {
// will be added later.
// vstr_t line;
bool cont_line;
bool paste_mode;
} repl_t;
repl_t repl;
@ -207,6 +208,7 @@ STATIC int pyexec_friendly_repl_process_char(int c);
void pyexec_event_repl_init(void) {
MP_STATE_VM(repl_line) = vstr_new(32);
repl.cont_line = false;
repl.paste_mode = false;
// no prompt before printing friendly REPL banner or entering raw REPL
readline_init(MP_STATE_VM(repl_line), "");
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
@ -226,6 +228,7 @@ STATIC int pyexec_raw_repl_process_char(int c) {
pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
vstr_reset(MP_STATE_VM(repl_line));
repl.cont_line = false;
repl.paste_mode = false;
pyexec_friendly_repl_process_char(CHAR_CTRL_B);
return 0;
} else if (c == CHAR_CTRL_C) {
@ -263,6 +266,32 @@ reset:
}
STATIC int pyexec_friendly_repl_process_char(int c) {
if (repl.paste_mode) {
if (c == CHAR_CTRL_C) {
// cancel everything
mp_hal_stdout_tx_str("\r\n");
goto input_restart;
} else if (c == CHAR_CTRL_D) {
// end of input
mp_hal_stdout_tx_str("\r\n");
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);
if (ret & PYEXEC_FORCED_EXIT) {
return ret;
}
goto input_restart;
} else {
// add char to buffer and echo
vstr_add_byte(MP_STATE_VM(repl_line), c);
if (c == '\r') {
mp_hal_stdout_tx_str("\r\n=== ");
} else {
char buf[1] = {c};
mp_hal_stdout_tx_strn(buf, 1);
}
return 0;
}
}
int ret = readline_process_char(c);
if (!repl.cont_line) {
@ -289,6 +318,12 @@ STATIC int pyexec_friendly_repl_process_char(int c) {
mp_hal_stdout_tx_str("\r\n");
vstr_clear(MP_STATE_VM(repl_line));
return PYEXEC_FORCED_EXIT;
} else if (ret == CHAR_CTRL_E) {
// paste mode
mp_hal_stdout_tx_str("\r\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\r\n=== ");
vstr_reset(MP_STATE_VM(repl_line));
repl.paste_mode = true;
return 0;
}
if (ret < 0) {
@ -335,6 +370,7 @@ STATIC int pyexec_friendly_repl_process_char(int c) {
input_restart:
vstr_reset(MP_STATE_VM(repl_line));
repl.cont_line = false;
repl.paste_mode = false;
readline_init(MP_STATE_VM(repl_line), ">>> ");
return 0;
}
@ -450,11 +486,17 @@ friendly_repl_reset:
// do the user a favor and reenable interrupts.
if (query_irq() == IRQ_STATE_DISABLED) {
enable_irq(IRQ_STATE_ENABLED);
mp_hal_stdout_tx_str("PYB: enabling IRQs\r\n");
mp_hal_stdout_tx_str("MPY: enabling IRQs\r\n");
}
}
#endif
// If the GC is locked at this point there is no way out except a reset,
// so force the GC to be unlocked to help the user debug what went wrong.
if (MP_STATE_MEM(gc_lock_depth) != 0) {
MP_STATE_MEM(gc_lock_depth) = 0;
}
vstr_reset(&line);
int ret = readline(&line, ">>> ");
mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
@ -535,20 +577,32 @@ int pyexec_file(const char *filename, pyexec_result_t *result) {
return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME, result);
}
int pyexec_file_if_exists(const char *filename, pyexec_result_t *result) {
#if MICROPY_MODULE_FROZEN
if (mp_frozen_stat(filename) == MP_IMPORT_STAT_FILE) {
return pyexec_frozen_module(filename, result);
}
#endif
if (mp_import_stat(filename) != MP_IMPORT_STAT_FILE) {
return 1; // success (no file is the same as an empty file executing without fail)
}
return pyexec_file(filename, result);
}
#if MICROPY_MODULE_FROZEN
int pyexec_frozen_module(const char *name) {
int pyexec_frozen_module(const char *name, pyexec_result_t *result) {
void *frozen_data;
int frozen_type = mp_find_frozen_module(name, strlen(name), &frozen_data);
switch (frozen_type) {
#if MICROPY_MODULE_FROZEN_STR
case MP_FROZEN_STR:
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, 0, NULL);
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, 0, result);
#endif
#if MICROPY_MODULE_FROZEN_MPY
case MP_FROZEN_MPY:
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_RAW_CODE, NULL);
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_RAW_CODE, result);
#endif
default:

View File

@ -54,7 +54,8 @@ extern int pyexec_system_exit;
int pyexec_raw_repl(void);
int pyexec_friendly_repl(void);
int pyexec_file(const char *filename, pyexec_result_t *result);
int pyexec_frozen_module(const char *name);
int pyexec_file_if_exists(const char *filename, pyexec_result_t *result);
int pyexec_frozen_module(const char *name, pyexec_result_t *result);
void pyexec_event_repl_init(void);
int pyexec_event_repl_process_char(int c);
extern uint8_t pyexec_repl_active;

View File

@ -172,7 +172,7 @@ STATIC const mp_obj_type_t stdio_buffer_obj_type = {
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &stdio_buffer_obj_stream_p,
.locals_dict = (mp_obj_t)&stdio_locals_dict,
.locals_dict = (mp_obj_dict_t *)&stdio_locals_dict,
};
STATIC const sys_stdio_obj_t stdio_buffer_obj = {{&stdio_buffer_obj_type}, .fd = 0}; // fd unused

Some files were not shown because too many files have changed in this diff Show More