-
Notifications
You must be signed in to change notification settings - Fork 0
[tryspaceorg/tryspace-lab#26] EPS #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,75 +1,126 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| #include "simulith.h" | ||||||||||||||||||||||||||||||||||||||||||||||
| #include <errno.h> | ||||||||||||||||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||||||||||||||||
| * Simulith I2C - Requirements | ||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||
| * Shall utilize ZMQ to communicate between nodes | ||||||||||||||||||||||||||||||||||||||||||||||
| * Shall have functions to initialize, read, write, transaction (both write then read), and close | ||||||||||||||||||||||||||||||||||||||||||||||
| * Shall communicate directly to the other end of the node | ||||||||||||||||||||||||||||||||||||||||||||||
| * Shall not block on any function | ||||||||||||||||||||||||||||||||||||||||||||||
| * Shall fail gracefully if peer is unavailable and return error codes (non-zero) instead of crashing. | ||||||||||||||||||||||||||||||||||||||||||||||
| * Shall not rely on a server as each node will be initialized with its name and destination. | ||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| #define MAX_I2C_BUSES 8 | ||||||||||||||||||||||||||||||||||||||||||||||
| #include "simulith_i2c.h" | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| typedef struct | ||||||||||||||||||||||||||||||||||||||||||||||
| int simulith_i2c_init(i2c_device_t *device) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| bool initialized; | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_i2c_read_callback read_cb; | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_i2c_write_callback write_cb; | ||||||||||||||||||||||||||||||||||||||||||||||
| } i2c_bus_t; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!device) return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (device->init == SIMULITH_I2C_INITIALIZED) return SIMULITH_I2C_SUCCESS; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| static i2c_bus_t i2c_buses[MAX_I2C_BUSES] = {0}; | ||||||||||||||||||||||||||||||||||||||||||||||
| device->zmq_ctx = zmq_ctx_new(); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!device->zmq_ctx) { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_init: Failed to create ZMQ context\n"); | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| device->zmq_sock = zmq_socket(device->zmq_ctx, ZMQ_PAIR); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!device->zmq_sock) { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_init: Failed to create ZMQ socket\n"); | ||||||||||||||||||||||||||||||||||||||||||||||
| zmq_ctx_term(device->zmq_ctx); | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (strlen(device->name) > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||
| zmq_setsockopt(device->zmq_sock, ZMQ_IDENTITY, device->name, strlen(device->name)); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| int rc; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (device->is_server) { | ||||||||||||||||||||||||||||||||||||||||||||||
| rc = zmq_bind(device->zmq_sock, device->address); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (rc != 0) { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_init: Failed to bind to %s\n", device->address); | ||||||||||||||||||||||||||||||||||||||||||||||
| zmq_close(device->zmq_sock); | ||||||||||||||||||||||||||||||||||||||||||||||
| zmq_ctx_term(device->zmq_ctx); | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_init: Bound to %s as '%s'\n", device->address, device->name); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| rc = zmq_connect(device->zmq_sock, device->address); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (rc != 0) { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_init: Failed to connect to %s\n", device->address); | ||||||||||||||||||||||||||||||||||||||||||||||
| zmq_close(device->zmq_sock); | ||||||||||||||||||||||||||||||||||||||||||||||
| zmq_ctx_term(device->zmq_ctx); | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_init: Connected to %s as '%s'\n", device->address, device->name); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| device->init = SIMULITH_I2C_INITIALIZED; | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_SUCCESS; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| int simulith_i2c_init(uint8_t bus_id, simulith_i2c_read_callback read_cb, simulith_i2c_write_callback write_cb) | ||||||||||||||||||||||||||||||||||||||||||||||
| int simulith_i2c_write(i2c_device_t *device, const uint8_t *data, size_t len) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (bus_id >= MAX_I2C_BUSES) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("Invalid I2C bus ID: %d\n", bus_id); | ||||||||||||||||||||||||||||||||||||||||||||||
| errno = EINVAL; | ||||||||||||||||||||||||||||||||||||||||||||||
| return -1; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!device || device->init != SIMULITH_I2C_INITIALIZED) { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_write: Uninitialized I2C device\n"); | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (!read_cb || !write_cb) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("Invalid I2C callbacks\n"); | ||||||||||||||||||||||||||||||||||||||||||||||
| errno = EINVAL; | ||||||||||||||||||||||||||||||||||||||||||||||
| return -1; | ||||||||||||||||||||||||||||||||||||||||||||||
| int rc = zmq_send(device->zmq_sock, data, len, ZMQ_DONTWAIT); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (rc < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_write: zmq_send failed (peer may be unavailable)\n"); | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| i2c_buses[bus_id].initialized = true; | ||||||||||||||||||||||||||||||||||||||||||||||
| i2c_buses[bus_id].read_cb = read_cb; | ||||||||||||||||||||||||||||||||||||||||||||||
| i2c_buses[bus_id].write_cb = write_cb; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("I2C bus %d initialized\n", bus_id); | ||||||||||||||||||||||||||||||||||||||||||||||
| return 0; | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("I2C TX[%s]: %zu bytes\n", device->name, len); | ||||||||||||||||||||||||||||||||||||||||||||||
| return (int)len; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| int simulith_i2c_read(uint8_t bus_id, uint8_t addr, uint8_t reg, uint8_t *data, size_t len) | ||||||||||||||||||||||||||||||||||||||||||||||
| int simulith_i2c_read(i2c_device_t *device, uint8_t *data, size_t len) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (bus_id >= MAX_I2C_BUSES || !i2c_buses[bus_id].initialized) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("Invalid or uninitialized I2C bus: %d\n", bus_id); | ||||||||||||||||||||||||||||||||||||||||||||||
| errno = EINVAL; | ||||||||||||||||||||||||||||||||||||||||||||||
| return -1; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!device || device->init != SIMULITH_I2C_INITIALIZED) { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_read: Uninitialized I2C device\n"); | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (!data || len == 0) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("Invalid read parameters\n"); | ||||||||||||||||||||||||||||||||||||||||||||||
| errno = EINVAL; | ||||||||||||||||||||||||||||||||||||||||||||||
| return -1; | ||||||||||||||||||||||||||||||||||||||||||||||
| int rc = zmq_recv(device->zmq_sock, data, len, ZMQ_DONTWAIT); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (rc < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (zmq_errno() == EAGAIN) { | ||||||||||||||||||||||||||||||||||||||||||||||
| // No data available, non-blocking | ||||||||||||||||||||||||||||||||||||||||||||||
| return 0; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("simulith_i2c_read: zmq_recv failed (peer may be unavailable)\n"); | ||||||||||||||||||||||||||||||||||||||||||||||
| return SIMULITH_I2C_ERROR; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return i2c_buses[bus_id].read_cb(addr, reg, data, len); | ||||||||||||||||||||||||||||||||||||||||||||||
| simulith_log("I2C RX[%s]: %d bytes\n", device->name, rc); | ||||||||||||||||||||||||||||||||||||||||||||||
| return rc; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
| return rc; | |
| zmq_msg_t msg; | |
| if (zmq_msg_init(&msg) != 0) { | |
| simulith_log("simulith_i2c_read: zmq_msg_init failed\n"); | |
| return SIMULITH_I2C_ERROR; | |
| } | |
| int rc = zmq_msg_recv(&msg, device->zmq_sock, ZMQ_DONTWAIT); | |
| if (rc < 0) { | |
| zmq_msg_close(&msg); | |
| if (zmq_errno() == EAGAIN) { | |
| // No data available, non-blocking | |
| return 0; | |
| } | |
| simulith_log("simulith_i2c_read: zmq_msg_recv failed (peer may be unavailable)\n"); | |
| return SIMULITH_I2C_ERROR; | |
| } | |
| size_t msg_size = zmq_msg_size(&msg); | |
| size_t copy_size = msg_size < len ? msg_size : len; | |
| memcpy(data, zmq_msg_data(&msg), copy_size); | |
| zmq_msg_close(&msg); | |
| simulith_log("I2C RX[%s]: %zu bytes (received %zu, copied %zu)\n", device->name, msg_size, msg_size, copy_size); | |
| return (int)copy_size; |
Copilot
AI
Aug 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a magic number (0) instead of a defined constant for the uninitialized state. Consider defining SIMULITH_I2C_UNINITIALIZED or similar constant for consistency with SIMULITH_I2C_INITIALIZED.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of zmq_setsockopt is not checked. If setting the socket identity fails, it could lead to unexpected behavior in peer identification.