property.c
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!! VERY IMPORTANT !!! !!!
* !!! For new ports, DISABLE prop_request_change first (see below) !!! !!!
* !!! BEFORE enabling it, check and double-check that meaning and valid range of values for each prop_request_change call !!!
* !!! are identical to the ones from fully working ports. !!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
/** \file
* Property handler installation
*
* Rather than registering a handler for each property (which seems to overload DryOS),
* it's probably better to have a single global property handler.
*
* Old implementation: property-old.c
*/
#include "dryos.h"
#include "property.h"
#include "bmp.h"
static void * global_token;
static void global_token_handler( void * token)
{
global_token = token;
}
int current_prop_handler = 0;
static void *
global_property_handler(
unsigned property,
void * UNUSED_ATTR( priv ),
void * buf,
unsigned len
)
{
#ifdef CONFIG_5DC
if (property == 0x80010001) return (void*)_prop_cleanup(global_token, property);
#endif
//~ bfnt_puts("Global prop", 0, 0, COLOR_BLACK, COLOR_WHITE);
extern struct prop_handler _prop_handlers_start[];
extern struct prop_handler _prop_handlers_end[];
struct prop_handler * handler = _prop_handlers_start;
for( ; handler < _prop_handlers_end ; handler++ )
{
if (handler->property == property)
{
//~ bmp_printf(FONT_LARGE, 0, 0, "%x %x...", property, handler->handler);
current_prop_handler = property;
handler->handler(property, priv, buf, len);
current_prop_handler = 0;
//~ bmp_printf(FONT_LARGE, 0, 0, "%x %x :)", property, handler->handler);
}
}
return (void*)_prop_cleanup(global_token, property);
}
static unsigned property_list[256];
void
prop_init( void* unused )
{
int actual_num_properties = 0;
extern struct prop_handler _prop_handlers_start[];
extern struct prop_handler _prop_handlers_end[];
struct prop_handler * handler = _prop_handlers_start;
for( ; handler < _prop_handlers_end ; handler++ )
{
int duplicate = 0;
for (int i = 0; i < actual_num_properties; i++)
{
if (_prop_handlers_start[i].property == handler->property)
{
duplicate = 1;
break;
}
}
if (!duplicate)
{
property_list[actual_num_properties] = handler->property;
actual_num_properties++;
}
if (actual_num_properties >= COUNT(property_list))
{
bfnt_puts("Too many prop handlers", 0, 0, COLOR_BLACK, COLOR_WHITE);
break;
}
}
prop_register_slave(
property_list,
actual_num_properties,
global_property_handler,
&global_token,
global_token_handler
);
}
// for reading simple integer properties
// not reliable in realtime scenarios (race condition?)
int _get_prop(int prop)
{
int* data = 0;
size_t len = 0;
int err = prop_get_value(prop, (void **) &data, &len);
if (!err) return data[0];
return 0;
}
// for strings
// not reliable in realtime scenarios (race condition?)
char* _get_prop_str(int prop)
{
char* data = 0;
size_t len = 0;
int err = prop_get_value(prop, (void **) &data, &len);
if (!err) return data;
return 0;
}
/* not reliable
// prop_get_value may take a long time to run, so let's try to use a small cache
int _get_prop_len_uncached(int prop)
{
int* data = 0;
size_t len = 0;
int err = prop_get_value(prop, (void **) &data, &len);
if (!err) return (int)len;
return 0;
}
// plc = property length cache
// circular buffer
static int plc_prop[32] = {0};
static int plc_len[32] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static int plc_i = 0;
int _get_prop_len(int prop)
{
for (int i = 0; i < 32; i++)
{
if (plc_prop[i] == prop && plc_len[i] >= 0)
return plc_len[i];
}
int len = get_prop_len_uncached(prop);
plc_prop[plc_i] = prop;
plc_len[plc_i] = len;
plc_i = (plc_i + 1) % 32;
return len;
}*/
/**
* This is just a safe wrapper for changing camera settings (well... only slightly safer than Canon's)
* Double-check the len parameter => less chances that our call will cause permanent damage.
*/
/**
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!! VERY IMPORTANT !!! !!!
* !!! For new ports, DISABLE this function first!!! !!!
* !!! BEFORE enabling it, check and double-check that meaning and valid range of values for each prop_request_change call !!!
* !!! are identical to the ones from fully working ports. !!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
void prop_request_change(unsigned property, const void* addr, size_t len)
{
/* problem: get_prop_len may return 0 :(
int correct_len = get_prop_len((int)property);
if (property == PROP_BATTERY_REPORT && len == 1) goto ok; // exception: this call is correct for polling battery level
if (correct_len != (int)len)
{
char msg[100];
snprintf(msg, sizeof(msg), "PROP_LEN(%x) correct:%x called:%x", property, correct_len, len);
bmp_printf(FONT(FONT_LARGE, COLOR_WHITE, COLOR_RED), 100, 100, msg);
ml_assert_handler(msg, __FILE__, __LINE__, __func__);
//~ ASSERT(PROP_LEN_INCORRECT);
info_led_blink(10,50,50);
return;
}
ok:
*/
//~ console_printf("prop:%x data:%x len:%x\n", property, MEM(addr), len);
_prop_request_change(property, addr, len);
}
/**
* For new ports, disable this function on first boots (although it should be pretty much harmless).
*/
INIT_FUNC( __FILE__, prop_init );