Tab5 camera + other stuff (#558)
* Tab5 camera + other stuff Tab5 camera driver - SC2356 Custom SliderBox widget - slider with plus and minus buttons + value label and snapping Rtc Time service + rtc api Sdk release - only include drivers built for that specific target, eg: sc2356 driver is mipi / p4 only. No more hardcoded manual sdk cmakelists New function to find device by compatible string match. no more static cast bool wildness when trying to match a single device (like M5Stack PaperS3 for example) * feedback + fixes Fixed external app user data path. fix(gui): block app teardown until onHide() completes, preventing ELF unload racing a still-running app added camera device type and api * drain the snake sssem --------- Co-authored-by: Ken Van Hoeylandt <git@kenvanhoeylandt.net>
This commit is contained in:
@@ -299,6 +299,14 @@ struct Device* device_find_first_active_by_type(const struct DeviceType* type);
|
||||
*/
|
||||
struct Device* device_find_first_by_type(const struct DeviceType* type);
|
||||
|
||||
/**
|
||||
* Find the first device whose driver matches the given compatible string.
|
||||
*
|
||||
* @param[in] compatible non-null compatible string to match
|
||||
* @return the first matching device, or NULL if none found
|
||||
*/
|
||||
struct Device* device_find_first_by_compatible(const char* compatible);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Handle to an open camera stream (see camera_open).
|
||||
*
|
||||
* The `device` field identifies the owning camera device so that camera_get_frame/
|
||||
* camera_close/etc. can dispatch to the correct driver; implementations embed this as
|
||||
* the first member (C) or base class (C++) of a larger private struct and may store
|
||||
* additional state after it.
|
||||
*/
|
||||
struct CameraHandleData {
|
||||
struct Device* device;
|
||||
};
|
||||
|
||||
typedef struct CameraHandleData* CameraHandle;
|
||||
|
||||
/** Clockwise rotation applied to frames */
|
||||
typedef enum {
|
||||
CAMERA_ROTATION_0 = 0,
|
||||
CAMERA_ROTATION_90 = 90,
|
||||
CAMERA_ROTATION_180 = 180,
|
||||
CAMERA_ROTATION_270 = 270,
|
||||
} CameraRotation;
|
||||
|
||||
/**
|
||||
* @brief API for camera drivers.
|
||||
*/
|
||||
struct CameraApi {
|
||||
/**
|
||||
* @brief Opens the camera and starts streaming.
|
||||
* @param[in] device the camera device
|
||||
* @param[out] out_handle receives the opened camera handle
|
||||
* @return ERROR_NONE on success
|
||||
*/
|
||||
error_t (*open)(struct Device* device, CameraHandle* out_handle);
|
||||
|
||||
/**
|
||||
* @brief Stops streaming and releases all resources associated with the handle.
|
||||
* @param[in] handle handle returned by open
|
||||
* @return ERROR_NONE on success
|
||||
*/
|
||||
error_t (*close)(CameraHandle handle);
|
||||
|
||||
/**
|
||||
* @brief Dequeues one RGB565 frame. Blocks until a frame is available or the timeout expires.
|
||||
* The caller must call release_frame to return the buffer to the camera queue.
|
||||
* @param[in] handle handle returned by open
|
||||
* @param[out] buf pointer to the frame buffer
|
||||
* @param[out] len byte length of buf
|
||||
* @param[in] timeout_ms maximum time to wait in milliseconds
|
||||
* @param[out] out_width optional: width of buf at the moment it was produced (may be NULL)
|
||||
* @param[out] out_height optional: height of buf at the moment it was produced (may be NULL)
|
||||
* @retval ERROR_NONE on success
|
||||
* @retval ERROR_TIMEOUT if no frame arrived in time
|
||||
*/
|
||||
error_t (*get_frame)(CameraHandle handle, uint8_t** buf, size_t* len, uint32_t timeout_ms, uint32_t* out_width, uint32_t* out_height);
|
||||
|
||||
/**
|
||||
* @brief Returns the last dequeued frame buffer to the capture queue.
|
||||
* Must be called after each successful get_frame.
|
||||
* @param[in] handle handle returned by open
|
||||
* @return ERROR_NONE on success
|
||||
*/
|
||||
error_t (*release_frame)(CameraHandle handle);
|
||||
|
||||
/** @brief Returns the current frame width in pixels. */
|
||||
uint32_t (*get_width)(CameraHandle handle);
|
||||
|
||||
/** @brief Returns the current frame height in pixels. */
|
||||
uint32_t (*get_height)(CameraHandle handle);
|
||||
|
||||
/**
|
||||
* @brief Changes the clockwise rotation applied to subsequent frames.
|
||||
* Can be called at any time while the handle is open, including during streaming.
|
||||
* @param[in] handle handle returned by open
|
||||
* @param[in] rotation new rotation
|
||||
* @return ERROR_NONE on success
|
||||
*/
|
||||
error_t (*set_rotation)(CameraHandle handle, CameraRotation rotation);
|
||||
|
||||
/**
|
||||
* @brief Captures one frame and JPEG-encodes it.
|
||||
* @param[in] handle handle returned by open
|
||||
* @param[out] out_buf pointer to JPEG-encoded data (caller must free with heap_caps_free)
|
||||
* @param[out] out_len byte length of JPEG data
|
||||
* @param[in] quality JPEG quality 1-100
|
||||
* @return ERROR_NONE on success
|
||||
*/
|
||||
error_t (*capture_jpeg)(CameraHandle handle, uint8_t** out_buf, size_t* out_len, uint8_t quality);
|
||||
};
|
||||
|
||||
/** @brief See CameraApi::open */
|
||||
error_t camera_open(struct Device* device, CameraHandle* out_handle);
|
||||
|
||||
/** @brief See CameraApi::close */
|
||||
error_t camera_close(CameraHandle handle);
|
||||
|
||||
/** @brief See CameraApi::get_frame */
|
||||
error_t camera_get_frame(CameraHandle handle, uint8_t** buf, size_t* len, uint32_t timeout_ms, uint32_t* out_width, uint32_t* out_height);
|
||||
|
||||
/** @brief See CameraApi::release_frame */
|
||||
error_t camera_release_frame(CameraHandle handle);
|
||||
|
||||
/** @brief See CameraApi::get_width */
|
||||
uint32_t camera_get_width(CameraHandle handle);
|
||||
|
||||
/** @brief See CameraApi::get_height */
|
||||
uint32_t camera_get_height(CameraHandle handle);
|
||||
|
||||
/** @brief See CameraApi::set_rotation */
|
||||
error_t camera_set_rotation(CameraHandle handle, CameraRotation rotation);
|
||||
|
||||
/** @brief See CameraApi::capture_jpeg */
|
||||
error_t camera_capture_jpeg(CameraHandle handle, uint8_t** out_buf, size_t* out_len, uint8_t quality);
|
||||
|
||||
extern const struct DeviceType CAMERA_TYPE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct RtcDateTime {
|
||||
uint16_t year; // 2000–2199
|
||||
uint8_t month; // 1–12
|
||||
uint8_t day; // 1–31
|
||||
uint8_t hour; // 0–23
|
||||
uint8_t minute; // 0–59
|
||||
uint8_t second; // 0–59
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief API for RTC (real-time clock) drivers.
|
||||
*/
|
||||
struct RtcApi {
|
||||
/**
|
||||
* @brief Reads the current date and time from the RTC.
|
||||
* @param[in] device the RTC device
|
||||
* @param[out] dt pointer to store the current date and time
|
||||
* @return ERROR_NONE on success
|
||||
*/
|
||||
error_t (*get_time)(struct Device* device, struct RtcDateTime* dt);
|
||||
|
||||
/**
|
||||
* @brief Writes the date and time to the RTC.
|
||||
* @param[in] device the RTC device
|
||||
* @param[in] dt the date and time to write
|
||||
* @return ERROR_NONE on success
|
||||
*/
|
||||
error_t (*set_time)(struct Device* device, const struct RtcDateTime* dt);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Reads the current date and time using the specified RTC device.
|
||||
*/
|
||||
error_t rtc_get_time(struct Device* device, struct RtcDateTime* dt);
|
||||
|
||||
/**
|
||||
* @brief Writes the date and time using the specified RTC device.
|
||||
*/
|
||||
error_t rtc_set_time(struct Device* device, const struct RtcDateTime* dt);
|
||||
|
||||
extern const struct DeviceType RTC_TYPE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -395,4 +395,18 @@ Device* device_find_first_by_type(const DeviceType* type) {
|
||||
return found;
|
||||
}
|
||||
|
||||
Device* device_find_first_by_compatible(const char* compatible) {
|
||||
struct Ctx { Device* found; const char* compatible; };
|
||||
Ctx ctx = { nullptr, compatible };
|
||||
device_for_each(&ctx, [](Device* dev, void* raw_ctx) -> bool {
|
||||
auto* c = static_cast<Ctx*>(raw_ctx);
|
||||
if (device_is_compatible(dev, c->compatible)) {
|
||||
c->found = dev;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return ctx.found;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <tactility/drivers/camera.h>
|
||||
#include <tactility/error.h>
|
||||
#include <tactility/device.h>
|
||||
|
||||
#define CAMERA_DRIVER_API(driver) ((struct CameraApi*)driver->api)
|
||||
|
||||
extern "C" {
|
||||
|
||||
error_t camera_open(Device* device, CameraHandle* out_handle) {
|
||||
const auto* driver = device_get_driver(device);
|
||||
return CAMERA_DRIVER_API(driver)->open(device, out_handle);
|
||||
}
|
||||
|
||||
error_t camera_close(CameraHandle handle) {
|
||||
const auto* driver = device_get_driver(handle->device);
|
||||
return CAMERA_DRIVER_API(driver)->close(handle);
|
||||
}
|
||||
|
||||
error_t camera_get_frame(CameraHandle handle, uint8_t** buf, size_t* len, uint32_t timeout_ms, uint32_t* out_width, uint32_t* out_height) {
|
||||
const auto* driver = device_get_driver(handle->device);
|
||||
return CAMERA_DRIVER_API(driver)->get_frame(handle, buf, len, timeout_ms, out_width, out_height);
|
||||
}
|
||||
|
||||
error_t camera_release_frame(CameraHandle handle) {
|
||||
const auto* driver = device_get_driver(handle->device);
|
||||
return CAMERA_DRIVER_API(driver)->release_frame(handle);
|
||||
}
|
||||
|
||||
uint32_t camera_get_width(CameraHandle handle) {
|
||||
const auto* driver = device_get_driver(handle->device);
|
||||
return CAMERA_DRIVER_API(driver)->get_width(handle);
|
||||
}
|
||||
|
||||
uint32_t camera_get_height(CameraHandle handle) {
|
||||
const auto* driver = device_get_driver(handle->device);
|
||||
return CAMERA_DRIVER_API(driver)->get_height(handle);
|
||||
}
|
||||
|
||||
error_t camera_set_rotation(CameraHandle handle, CameraRotation rotation) {
|
||||
const auto* driver = device_get_driver(handle->device);
|
||||
return CAMERA_DRIVER_API(driver)->set_rotation(handle, rotation);
|
||||
}
|
||||
|
||||
error_t camera_capture_jpeg(CameraHandle handle, uint8_t** out_buf, size_t* out_len, uint8_t quality) {
|
||||
const auto* driver = device_get_driver(handle->device);
|
||||
return CAMERA_DRIVER_API(driver)->capture_jpeg(handle, out_buf, out_len, quality);
|
||||
}
|
||||
|
||||
const struct DeviceType CAMERA_TYPE {
|
||||
.name = "camera"
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include <tactility/drivers/rtc.h>
|
||||
#include <tactility/device.h>
|
||||
|
||||
#define RTC_DRIVER_API(driver) ((struct RtcApi*)driver->api)
|
||||
|
||||
extern "C" {
|
||||
|
||||
error_t rtc_get_time(struct Device* device, struct RtcDateTime* dt) {
|
||||
const auto* driver = device_get_driver(device);
|
||||
return RTC_DRIVER_API(driver)->get_time(device, dt);
|
||||
}
|
||||
|
||||
error_t rtc_set_time(struct Device* device, const struct RtcDateTime* dt) {
|
||||
const auto* driver = device_get_driver(device);
|
||||
return RTC_DRIVER_API(driver)->set_time(device, dt);
|
||||
}
|
||||
|
||||
const struct DeviceType RTC_TYPE {
|
||||
.name = "rtc"
|
||||
};
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <tactility/drivers/bluetooth_serial.h>
|
||||
#include <tactility/drivers/bluetooth_midi.h>
|
||||
#include <tactility/drivers/bluetooth_hid_device.h>
|
||||
#include <tactility/drivers/camera.h>
|
||||
#include <tactility/drivers/usb_host_hid.h>
|
||||
#include <tactility/drivers/usb_host_midi.h>
|
||||
#include <tactility/drivers/usb_host_msc.h>
|
||||
@@ -16,6 +17,7 @@
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/i2s_controller.h>
|
||||
#include <tactility/drivers/root.h>
|
||||
#include <tactility/drivers/rtc.h>
|
||||
#include <tactility/drivers/spi_controller.h>
|
||||
#include <tactility/drivers/uart_controller.h>
|
||||
#include <tactility/drivers/wifi.h>
|
||||
@@ -65,6 +67,7 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = {
|
||||
DEFINE_MODULE_SYMBOL(device_find_by_name),
|
||||
DEFINE_MODULE_SYMBOL(device_find_first_active_by_type),
|
||||
DEFINE_MODULE_SYMBOL(device_find_first_by_type),
|
||||
DEFINE_MODULE_SYMBOL(device_find_first_by_compatible),
|
||||
// driver
|
||||
DEFINE_MODULE_SYMBOL(driver_construct),
|
||||
DEFINE_MODULE_SYMBOL(driver_destruct),
|
||||
@@ -118,6 +121,10 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = {
|
||||
DEFINE_MODULE_SYMBOL(I2S_CONTROLLER_TYPE),
|
||||
// drivers/root
|
||||
DEFINE_MODULE_SYMBOL(root_is_model),
|
||||
// drivers/rtc
|
||||
DEFINE_MODULE_SYMBOL(rtc_get_time),
|
||||
DEFINE_MODULE_SYMBOL(rtc_set_time),
|
||||
DEFINE_MODULE_SYMBOL(RTC_TYPE),
|
||||
// drivers/spi_controller
|
||||
DEFINE_MODULE_SYMBOL(spi_controller_lock),
|
||||
DEFINE_MODULE_SYMBOL(spi_controller_try_lock),
|
||||
@@ -182,6 +189,16 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = {
|
||||
DEFINE_MODULE_SYMBOL(bluetooth_hid_device_send_gamepad),
|
||||
DEFINE_MODULE_SYMBOL(bluetooth_hid_device_is_connected),
|
||||
DEFINE_MODULE_SYMBOL(BLUETOOTH_HID_DEVICE_TYPE),
|
||||
// drivers/camera
|
||||
DEFINE_MODULE_SYMBOL(camera_open),
|
||||
DEFINE_MODULE_SYMBOL(camera_close),
|
||||
DEFINE_MODULE_SYMBOL(camera_get_frame),
|
||||
DEFINE_MODULE_SYMBOL(camera_release_frame),
|
||||
DEFINE_MODULE_SYMBOL(camera_get_width),
|
||||
DEFINE_MODULE_SYMBOL(camera_get_height),
|
||||
DEFINE_MODULE_SYMBOL(camera_set_rotation),
|
||||
DEFINE_MODULE_SYMBOL(camera_capture_jpeg),
|
||||
DEFINE_MODULE_SYMBOL(CAMERA_TYPE),
|
||||
// drivers/wifi
|
||||
DEFINE_MODULE_SYMBOL(wifi_find_first_registered_device),
|
||||
DEFINE_MODULE_SYMBOL(wifi_get_radio_state),
|
||||
|
||||
Reference in New Issue
Block a user