driver/sensors: support custom type of sensor.
For examples, the custom sensor could define: struct custem_event_s { uint64_t timestamp; int16_t adc[8]; }; struct sensor_lowerhalf_s g_lower = { .buffer_size = 1024, }; sensor_custom_register(lower, "/dev/sensor/custom0", sizeof(struct custem_event_s)); Signed-off-by: dongjiuzhu <dongjiuzhu1@xiaomi.com>
This commit is contained in:
parent
4ce935f711
commit
148afd9548
@ -69,6 +69,7 @@ struct sensor_upperhalf_s
|
||||
FAR struct pollfd *fds[CONFIG_SENSORS_NPOLLWAITERS];
|
||||
FAR struct sensor_lowerhalf_s *lower; /* the handle of lower half driver */
|
||||
struct circbuf_s buffer; /* The circular buffer of sensor device */
|
||||
uint8_t esize; /* The element size of circular buffer */
|
||||
uint8_t crefs; /* Number of times the device has been opened */
|
||||
sem_t exclsem; /* Manages exclusive access to file operations */
|
||||
sem_t buffersem; /* Wakeup user waiting for data in circular buffer */
|
||||
@ -98,6 +99,7 @@ static int sensor_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
|
||||
static const struct sensor_info g_sensor_info[] =
|
||||
{
|
||||
{0, NULL},
|
||||
{sizeof(struct sensor_event_accel), "accel"},
|
||||
{sizeof(struct sensor_event_mag), "mag"},
|
||||
{sizeof(struct sensor_event_gyro), "gyro"},
|
||||
@ -172,7 +174,6 @@ static int sensor_open(FAR struct file *filep)
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct sensor_upperhalf_s *upper = inode->i_private;
|
||||
FAR struct sensor_lowerhalf_s *lower = upper->lower;
|
||||
size_t bytes;
|
||||
uint8_t tmp;
|
||||
int ret;
|
||||
|
||||
@ -194,8 +195,7 @@ static int sensor_open(FAR struct file *filep)
|
||||
{
|
||||
/* Initialize sensor buffer */
|
||||
|
||||
bytes = ROUNDUP(lower->buffer_size, g_sensor_info[lower->type].esize);
|
||||
ret = circbuf_init(&upper->buffer, NULL, bytes);
|
||||
ret = circbuf_init(&upper->buffer, NULL, lower->buffer_size);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err;
|
||||
@ -243,7 +243,6 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
|
||||
FAR struct sensor_upperhalf_s *upper = inode->i_private;
|
||||
FAR struct sensor_lowerhalf_s *lower = upper->lower;
|
||||
ssize_t ret;
|
||||
size_t bytes;
|
||||
|
||||
if (!buffer || !len)
|
||||
{
|
||||
@ -319,9 +318,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
|
||||
circbuf_size(&upper->buffer) > lower->buffer_size &&
|
||||
circbuf_used(&upper->buffer) <= lower->buffer_size)
|
||||
{
|
||||
bytes = ROUNDUP(lower->buffer_size,
|
||||
g_sensor_info[lower->type].esize);
|
||||
ret = circbuf_resize(&upper->buffer, bytes);
|
||||
ret = circbuf_resize(&upper->buffer, lower->buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,10 +401,8 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
/* Adjust length of buffer in batch mode */
|
||||
|
||||
bytes = ROUNDUP(ROUNDUP(*val, upper->interval) /
|
||||
upper->interval *
|
||||
g_sensor_info[lower->type].esize +
|
||||
lower->buffer_size,
|
||||
g_sensor_info[lower->type].esize);
|
||||
upper->interval * upper->esize +
|
||||
lower->buffer_size, upper->esize);
|
||||
|
||||
ret = circbuf_resize(&upper->buffer, bytes);
|
||||
}
|
||||
@ -417,7 +412,7 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
case SNIOC_GET_NEVENTBUF:
|
||||
{
|
||||
*val = lower->buffer_size / g_sensor_info[lower->type].esize;
|
||||
*val = lower->buffer_size / upper->esize;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -425,11 +420,8 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
if (*val != 0)
|
||||
{
|
||||
lower->buffer_size = ROUNDUP(*val,
|
||||
g_sensor_info[lower->type].esize);
|
||||
bytes = ROUNDUP(lower->buffer_size,
|
||||
g_sensor_info[lower->type].esize);
|
||||
ret = circbuf_resize(&upper->buffer, bytes);
|
||||
lower->buffer_size = ROUNDUP(*val, upper->esize);
|
||||
ret = circbuf_resize(&upper->buffer, lower->buffer_size);
|
||||
if (ret >= 0)
|
||||
{
|
||||
*val = lower->buffer_size;
|
||||
@ -613,15 +605,53 @@ static void sensor_notify_event(FAR void *priv)
|
||||
|
||||
int sensor_register(FAR struct sensor_lowerhalf_s *lower, int devno)
|
||||
{
|
||||
FAR struct sensor_upperhalf_s *upper;
|
||||
char path[DEVNAME_MAX];
|
||||
|
||||
DEBUGASSERT(lower != NULL);
|
||||
|
||||
snprintf(path, DEVNAME_MAX, DEVNAME_FMT,
|
||||
g_sensor_info[lower->type].name,
|
||||
lower->uncalibrated ? DEVNAME_UNCAL : "",
|
||||
devno);
|
||||
return sensor_custom_register(lower, path,
|
||||
g_sensor_info[lower->type].esize);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_custom_register
|
||||
*
|
||||
* Description:
|
||||
* This function binds an instance of a "lower half" Sensor driver with the
|
||||
* "upper half" Sensor device and registers that device so that can be used
|
||||
* by application code.
|
||||
*
|
||||
* You can register the character device type by specific path and esize.
|
||||
* This API corresponds to the sensor_custom_unregister.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persists as long
|
||||
* as the driver persists.
|
||||
* path - The user specifies path of device. ex: /dev/sensor/xxx.
|
||||
* esize - The element size of intermediate circular buffer.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if the driver was successfully register; A negated errno value is
|
||||
* returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
|
||||
FAR const char *path, uint8_t esize)
|
||||
{
|
||||
FAR struct sensor_upperhalf_s *upper;
|
||||
int ret = -EINVAL;
|
||||
|
||||
DEBUGASSERT(lower != NULL);
|
||||
|
||||
if (lower->type >= SENSOR_TYPE_COUNT)
|
||||
if (lower->type >= SENSOR_TYPE_COUNT || !esize)
|
||||
{
|
||||
snerr("ERROR: Type is invalid\n");
|
||||
snerr("ERROR: type is invalid\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -637,6 +667,7 @@ int sensor_register(FAR struct sensor_lowerhalf_s *lower, int devno)
|
||||
/* Initialize the upper-half data structure */
|
||||
|
||||
upper->lower = lower;
|
||||
upper->esize = esize;
|
||||
|
||||
nxsem_init(&upper->exclsem, 0, 1);
|
||||
nxsem_init(&upper->buffersem, 0, 0);
|
||||
@ -651,7 +682,11 @@ int sensor_register(FAR struct sensor_lowerhalf_s *lower, int devno)
|
||||
{
|
||||
if (!lower->buffer_size)
|
||||
{
|
||||
lower->buffer_size = g_sensor_info[lower->type].esize;
|
||||
lower->buffer_size = esize;
|
||||
}
|
||||
else
|
||||
{
|
||||
lower->buffer_size = ROUNDUP(lower->buffer_size, esize);
|
||||
}
|
||||
|
||||
lower->push_event = sensor_push_event;
|
||||
@ -659,14 +694,10 @@ int sensor_register(FAR struct sensor_lowerhalf_s *lower, int devno)
|
||||
else
|
||||
{
|
||||
lower->notify_event = sensor_notify_event;
|
||||
lower->buffer_size = 0;
|
||||
}
|
||||
|
||||
snprintf(path, DEVNAME_MAX, DEVNAME_FMT,
|
||||
g_sensor_info[lower->type].name,
|
||||
lower->uncalibrated ? DEVNAME_UNCAL : "",
|
||||
devno);
|
||||
sninfo("Registering %s\n", path);
|
||||
|
||||
ret = register_driver(path, &g_sensor_fops, 0666, upper);
|
||||
if (ret)
|
||||
{
|
||||
@ -700,18 +731,39 @@ drv_err:
|
||||
|
||||
void sensor_unregister(FAR struct sensor_lowerhalf_s *lower, int devno)
|
||||
{
|
||||
FAR struct sensor_upperhalf_s *upper;
|
||||
char path[DEVNAME_MAX];
|
||||
|
||||
snprintf(path, DEVNAME_MAX, DEVNAME_FMT,
|
||||
g_sensor_info[lower->type].name,
|
||||
lower->uncalibrated ? DEVNAME_UNCAL : "",
|
||||
devno);
|
||||
sensor_custom_unregister(lower, path);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_custom_unregister
|
||||
*
|
||||
* Description:
|
||||
* This function unregister character node and release all resource about
|
||||
* upper half driver. This API corresponds to the sensor_custom_register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persists as long
|
||||
* as the driver persists.
|
||||
* path - The user specifies path of device, ex: /dev/sensor/xxx
|
||||
****************************************************************************/
|
||||
|
||||
void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *lower,
|
||||
FAR const char *path)
|
||||
{
|
||||
FAR struct sensor_upperhalf_s *upper;
|
||||
|
||||
DEBUGASSERT(lower != NULL);
|
||||
DEBUGASSERT(lower->priv != NULL);
|
||||
|
||||
upper = lower->priv;
|
||||
|
||||
snprintf(path, DEVNAME_MAX, DEVNAME_FMT,
|
||||
g_sensor_info[lower->type].name,
|
||||
lower->uncalibrated ? DEVNAME_UNCAL : "",
|
||||
devno);
|
||||
sninfo("UnRegistering %s\n", path);
|
||||
unregister_driver(path);
|
||||
|
||||
|
@ -40,142 +40,151 @@
|
||||
|
||||
/* sensor type definition */
|
||||
|
||||
/* Custom Sensor
|
||||
* Some special sensor whose event size is not fixed or dynamically change,
|
||||
* are called sensor of custom type. You should treat its events as byte
|
||||
* streams and use sensor_custom_register to register character device
|
||||
* with specific path, ex: "/dev/sensor/custom_dummy".
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_CUSTOM 0
|
||||
|
||||
/* Accelerometer
|
||||
* All values are in SI units (m/s^2), and measure the acceleration of the
|
||||
* device minus the acceleration dut to gravity.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_ACCELEROMETER 0
|
||||
#define SENSOR_TYPE_ACCELEROMETER 1
|
||||
|
||||
/* Magneric Field
|
||||
* All values are in micro-Tesla (uT) and measure the geomagnetic field
|
||||
* in X, Y and Z axis.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_MAGNETIC_FIELD 1
|
||||
#define SENSOR_TYPE_MAGNETIC_FIELD 2
|
||||
|
||||
/* Gyroscope
|
||||
* All values are in radians/second and measure the rate of rotation around
|
||||
* the X, Y and Z axis.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_GYROSCOPE 2
|
||||
#define SENSOR_TYPE_GYROSCOPE 3
|
||||
|
||||
/* Ambient Light
|
||||
* The ambient light sensor value is returned in SI units lux.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_LIGHT 3
|
||||
#define SENSOR_TYPE_LIGHT 4
|
||||
|
||||
/* Barometer
|
||||
* All values are in hectopascal (hPa) and measure the athmospheric pressure
|
||||
* we can calculate altitude by perssure.
|
||||
* All values are in hectopascal (hPa) and measure the athmospheric pressure.
|
||||
* You can calculate altitude by perssure.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_BAROMETER 4
|
||||
#define SENSOR_TYPE_BAROMETER 5
|
||||
|
||||
/* Proximity
|
||||
* The values correspond to the distance to the nearest
|
||||
* object in centimeters.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PROXIMITY 5
|
||||
#define SENSOR_TYPE_PROXIMITY 6
|
||||
|
||||
/* Relative Humidity
|
||||
* A relative humidity sensor measure relative ambient air humidity and
|
||||
* return a value in percent.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_RELATIVE_HUMIDITY 6
|
||||
#define SENSOR_TYPE_RELATIVE_HUMIDITY 7
|
||||
|
||||
/* Ambient Temperature
|
||||
* The ambient (room) temperature in degree Celsius
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_AMBIENT_TEMPERATURE 7
|
||||
#define SENSOR_TYPE_AMBIENT_TEMPERATURE 8
|
||||
|
||||
/* RGB
|
||||
* We use these values of RGB to weighted to obtain the color of LED.
|
||||
* These values is in unit percent.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_RGB 8
|
||||
#define SENSOR_TYPE_RGB 9
|
||||
|
||||
/* Hall
|
||||
* All values are in bool type (0 or 1) and it often is used to as switch.
|
||||
* A values of 1 indicates that switch on.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_HALL 9
|
||||
#define SENSOR_TYPE_HALL 10
|
||||
|
||||
/* IR (Infrared Ray)
|
||||
* This sensor can detect a human approach and outputs a signal from
|
||||
* interrupt pins. This sensor value is in lux.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_IR 10
|
||||
#define SENSOR_TYPE_IR 11
|
||||
|
||||
/* GPS
|
||||
* A sensor of this type returns gps data. Include year, month, day,
|
||||
* hour, minutes, seconds, altitude, longitude, latitude.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_GPS 11
|
||||
#define SENSOR_TYPE_GPS 12
|
||||
|
||||
/* Ultraviolet light sensor
|
||||
* This sensor can identify the UV index in ambient light help people
|
||||
* to effectively protect themselves from sunburns, cancer or eye damage.
|
||||
* This value range is 0 - 15.
|
||||
*/
|
||||
#define SENSOR_TYPE_ULTRAVIOLET 12
|
||||
#define SENSOR_TYPE_ULTRAVIOLET 13
|
||||
|
||||
/* Noise Loudness
|
||||
* A sensor of this type returns the loudness of noise in SI units (db)
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_NOISE 13
|
||||
#define SENSOR_TYPE_NOISE 14
|
||||
|
||||
/* PM25
|
||||
* A sensor of this type returns the content of pm2.5 in the air
|
||||
* This value is in SI units (ug/m^3)
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PM25 14
|
||||
#define SENSOR_TYPE_PM25 15
|
||||
|
||||
/* PM1P0
|
||||
* A sensor of this type returns the content of pm1.0 in the air
|
||||
* This value is in SI units (ug/m^3)
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PM1P0 15
|
||||
#define SENSOR_TYPE_PM1P0 16
|
||||
|
||||
/* PM10
|
||||
* A sensor of this type returns the content of pm10 in the air
|
||||
* This value is in SI units (ug/m^3)
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PM10 16
|
||||
#define SENSOR_TYPE_PM10 17
|
||||
|
||||
/* CO2
|
||||
* A sensor of this type returns the content of CO2 in the air
|
||||
* This vaule is in units (ppm-part per million).
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_CO2 17
|
||||
#define SENSOR_TYPE_CO2 18
|
||||
|
||||
/* HCHO
|
||||
* The HCHO pollution is an important indicator of household air
|
||||
* pollution. This value is in units (ppm-part per million).
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_HCHO 18
|
||||
#define SENSOR_TYPE_HCHO 19
|
||||
|
||||
/* TVOC (total volatile organic compounds)
|
||||
* The indoor TVOC is cause indoor air pollution is one of the
|
||||
* main reasons why. This value is in units (ppb-part per billion).
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_TVOC 19
|
||||
#define SENSOR_TYPE_TVOC 20
|
||||
|
||||
/* PH
|
||||
* The acid-base degree describes the strength of the aqueous
|
||||
@ -184,21 +193,21 @@
|
||||
* pH<7 is acidic, and pH>7 is alkaline.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PH 20
|
||||
#define SENSOR_TYPE_PH 21
|
||||
|
||||
/* Dust
|
||||
* A sensor of this type returns the content of dust in the air
|
||||
* values is in ug/m^3.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_DUST 21
|
||||
#define SENSOR_TYPE_DUST 22
|
||||
|
||||
/* Heart Rate
|
||||
* A sensor of this type returns the current heart rate.
|
||||
* Current heart rate is in beats per minute (BPM).
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_HEART_RATE 22
|
||||
#define SENSOR_TYPE_HEART_RATE 23
|
||||
|
||||
/* Heart Beat
|
||||
* A sensor of this type returns an event evetytime
|
||||
@ -206,11 +215,11 @@
|
||||
* to the positive peak in the QRS complex of and ECG signal.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_HEART_BEAT 23
|
||||
#define SENSOR_TYPE_HEART_BEAT 24
|
||||
|
||||
/* The total number of sensor */
|
||||
|
||||
#define SENSOR_TYPE_COUNT 24
|
||||
#define SENSOR_TYPE_COUNT 25
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
@ -532,7 +541,7 @@ struct sensor_ops_s
|
||||
/**************************************************************************
|
||||
* Name: control
|
||||
*
|
||||
* In this method, we allow user to set some special config for the sensor,
|
||||
* With this method, the user can set some special config for the sensor,
|
||||
* such as changing the custom mode, setting the custom resolution, reset,
|
||||
* etc, which are all parsed and implemented by lower half driver.
|
||||
*
|
||||
@ -648,9 +657,10 @@ extern "C"
|
||||
* "upper half" Sensor device and registers that device so that can be used
|
||||
* by application code.
|
||||
*
|
||||
* We will register the chararter device by node name format based on the
|
||||
* You can register the character device by node name format based on the
|
||||
* type of sensor. Multiple types of the same type are distinguished by
|
||||
* numbers. eg: accel0, accel1
|
||||
* numbers. eg: accel0, accel1. This type of sensor must be less than
|
||||
* SENSOR_TYPE_COUNT. This API corresponds to the sensor_unregister.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
@ -668,21 +678,64 @@ extern "C"
|
||||
int sensor_register(FAR struct sensor_lowerhalf_s *dev, int devno);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_unregister
|
||||
* Name: sensor_custom_register
|
||||
*
|
||||
* Description:
|
||||
* This function unregister character node and release all resource about
|
||||
* upper half driver.
|
||||
* This function binds an instance of a "lower half" Sensor driver with the
|
||||
* "upper half" Sensor device and registers that device so that can be used
|
||||
* by application code.
|
||||
*
|
||||
* You can register the character device type by specific path and esize.
|
||||
* This API corresponds to the sensor_custom_unregister.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persist as long
|
||||
* as the driver persists.
|
||||
* path - The user specifies path of device. ex: /dev/sensor/xxx.
|
||||
* esize - The element size of intermediate circular buffer.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if the driver was successfully register; A negated errno value is
|
||||
* returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int sensor_custom_register(FAR struct sensor_lowerhalf_s *dev,
|
||||
FAR const char *path, uint8_t esize);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_unregister
|
||||
*
|
||||
* Description:
|
||||
* This function unregisters character node and releases all resource from
|
||||
* upper half driver. This API corresponds to the sensor_register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persists as long
|
||||
* as the driver persists.
|
||||
* devno - The user specifies which device of this type, from 0.
|
||||
****************************************************************************/
|
||||
|
||||
void sensor_unregister(FAR struct sensor_lowerhalf_s *dev, int devno);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_custom_unregister
|
||||
*
|
||||
* Description:
|
||||
* This function unregisters character node and releases all resource from
|
||||
* upper half driver. This API corresponds to the sensor_custom_register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persists as long
|
||||
* as the driver persists.
|
||||
* path - The user specifies path of device, ex: /dev/sensor/xxx
|
||||
****************************************************************************/
|
||||
|
||||
void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *dev,
|
||||
FAR const char *path);
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user