1.设备支持挂载/卸载检测。
This commit is contained in:
@@ -288,7 +288,7 @@ int mr_pin_register(struct mr_pin *pin, const char *path,
|
|||||||
MR_ASSERT(path != NULL);
|
MR_ASSERT(path != NULL);
|
||||||
MR_ASSERT((driver != NULL) && (driver->ops != NULL));
|
MR_ASSERT((driver != NULL) && (driver->ops != NULL));
|
||||||
|
|
||||||
/* Register the pin device */
|
/* Register the pin */
|
||||||
return mr_device_register((struct mr_device *)pin, path,
|
return mr_device_register((struct mr_device *)pin, path,
|
||||||
MR_DEVICE_TYPE_PIN | MR_DEVICE_TYPE_FULL_DUPLEX,
|
MR_DEVICE_TYPE_PIN | MR_DEVICE_TYPE_FULL_DUPLEX,
|
||||||
&ops, driver);
|
&ops, driver);
|
||||||
|
|||||||
@@ -192,8 +192,7 @@ static ssize_t serial_write(struct mr_device *device, int pos, const void *buf,
|
|||||||
static int serial_ioctl(struct mr_device *device, int pos, int cmd, void *args)
|
static int serial_ioctl(struct mr_device *device, int pos, int cmd, void *args)
|
||||||
{
|
{
|
||||||
struct mr_serial *serial = (struct mr_serial *)device;
|
struct mr_serial *serial = (struct mr_serial *)device;
|
||||||
struct mr_driver *driver =
|
struct mr_driver *driver = _MR_DEVICE_DRIVER_GET(device);
|
||||||
_MR_DEVICE_DRIVER_GET((struct mr_device *)serial);
|
|
||||||
struct mr_serial_driver_ops *ops = _MR_DRIVER_OPS_GET(driver);
|
struct mr_serial_driver_ops *ops = _MR_DRIVER_OPS_GET(driver);
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
@@ -469,7 +468,7 @@ int mr_serial_register(struct mr_serial *serial, const char *path,
|
|||||||
serial->wfifo_size = MR_CFG_SERIAL_WR_FIFO_SIZE;
|
serial->wfifo_size = MR_CFG_SERIAL_WR_FIFO_SIZE;
|
||||||
serial->state = 0;
|
serial->state = 0;
|
||||||
|
|
||||||
/* Register the serial device */
|
/* Register the serial */
|
||||||
return mr_device_register(
|
return mr_device_register(
|
||||||
(struct mr_device *)serial, path,
|
(struct mr_device *)serial, path,
|
||||||
MR_DEVICE_TYPE_SERIAL | MR_DEVICE_TYPE_FULL_DUPLEX, &ops, driver);
|
MR_DEVICE_TYPE_SERIAL | MR_DEVICE_TYPE_FULL_DUPLEX, &ops, driver);
|
||||||
|
|||||||
@@ -214,6 +214,9 @@ struct mr_device_ops
|
|||||||
size_t count);
|
size_t count);
|
||||||
int (*ioctl)(struct mr_device *device, int pos, int cmd, void *args);
|
int (*ioctl)(struct mr_device *device, int pos, int cmd, void *args);
|
||||||
int (*isr)(struct mr_device *device, uint32_t event, void *args);
|
int (*isr)(struct mr_device *device, uint32_t event, void *args);
|
||||||
|
|
||||||
|
int (*attach)(struct mr_device *device, struct mr_device *source);
|
||||||
|
int (*detach)(struct mr_device *device, struct mr_device *source);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -110,6 +110,16 @@ static int _device_register_iter(struct mr_device *device, const char *path,
|
|||||||
return MR_EEXIST;
|
return MR_EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Notify the parent device that the child device will be attached */
|
||||||
|
if (parent->ops->attach != NULL)
|
||||||
|
{
|
||||||
|
int ret = parent->ops->attach(parent, device);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Register the device */
|
/* Register the device */
|
||||||
device->magic = _MAGIC_NUMBER;
|
device->magic = _MAGIC_NUMBER;
|
||||||
strncpy(device->name, path, sizeof(device->name));
|
strncpy(device->name, path, sizeof(device->name));
|
||||||
@@ -292,7 +302,7 @@ MR_INLINE int _device_take(struct mr_device *device, int descriptor,
|
|||||||
uint32_t lock;
|
uint32_t lock;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* If the device is not FDX, the read/write must be locked */
|
/* If the device is not FDX, the read/writing must be locked */
|
||||||
mask = (device->full_duplex == true) ? mask : _MR_OPERATE_MASK_ALL;
|
mask = (device->full_duplex == true) ? mask : _MR_OPERATE_MASK_ALL;
|
||||||
|
|
||||||
/* Calculate the lock mask, since the descriptor can be 0, need to add 1 */
|
/* Calculate the lock mask, since the descriptor can be 0, need to add 1 */
|
||||||
@@ -321,7 +331,7 @@ MR_INLINE int _device_take(struct mr_device *device, int descriptor,
|
|||||||
|
|
||||||
MR_INLINE void _device_release(struct mr_device *device, uint32_t mask)
|
MR_INLINE void _device_release(struct mr_device *device, uint32_t mask)
|
||||||
{
|
{
|
||||||
/* If the device is not FDX, the read/write must be locked */
|
/* If the device is not FDX, the read/writing must be locked */
|
||||||
mask = (device->full_duplex == true) ? mask : _MR_OPERATE_MASK_ALL;
|
mask = (device->full_duplex == true) ? mask : _MR_OPERATE_MASK_ALL;
|
||||||
|
|
||||||
/* Release the device lock */
|
/* Release the device lock */
|
||||||
@@ -418,28 +428,46 @@ static int _device_register(struct mr_device *device, const char *path,
|
|||||||
|
|
||||||
/* Critical section exit */
|
/* Critical section exit */
|
||||||
mr_critical_exit();
|
mr_critical_exit();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _device_unregister(struct mr_device *device)
|
static int _device_unregister(struct mr_device *device)
|
||||||
{
|
{
|
||||||
|
struct mr_device *parent = device->parent;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Critical section enter */
|
/* Critical section enter */
|
||||||
mr_critical_enter();
|
mr_critical_enter();
|
||||||
|
|
||||||
/* Unregister the device only when there are no more references to it */
|
/* Unregister the device only when there are no more references to it */
|
||||||
if (device->ref_count == 0)
|
if (device->ref_count > 0)
|
||||||
{
|
|
||||||
device->magic = 0;
|
|
||||||
mr_list_remove(&device->list);
|
|
||||||
device->parent = NULL;
|
|
||||||
ret = MR_EOK;
|
|
||||||
} else
|
|
||||||
{
|
{
|
||||||
ret = MR_EBUSY;
|
ret = MR_EBUSY;
|
||||||
|
goto _exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to detach the device from its parent */
|
||||||
|
mr_list_remove(&device->list);
|
||||||
|
|
||||||
|
/* Notify the parent device that the child device will be detached */
|
||||||
|
if (parent->ops->detach != NULL)
|
||||||
|
{
|
||||||
|
ret = parent->ops->detach(parent, device);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
/* Revert the list operation */
|
||||||
|
mr_list_insert_before(&parent->clist, &device->list);
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unregister the device */
|
||||||
|
device->magic = 0;
|
||||||
|
device->parent = NULL;
|
||||||
|
ret = MR_EOK;
|
||||||
|
|
||||||
|
_exit:
|
||||||
/* Critical section exit */
|
/* Critical section exit */
|
||||||
mr_critical_exit();
|
mr_critical_exit();
|
||||||
return ret;
|
return ret;
|
||||||
@@ -513,7 +541,7 @@ static int _device_open(const char *path, uint32_t flags)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Device will only be opened the first time it is accessed */
|
/* The Device will only be opened the first time it is accessed */
|
||||||
if ((device->ref_count == 0) && (device->ops->open != NULL))
|
if ((device->ref_count == 0) && (device->ops->open != NULL))
|
||||||
{
|
{
|
||||||
ret = device->ops->open(device);
|
ret = device->ops->open(device);
|
||||||
@@ -555,7 +583,7 @@ static int _device_close(int descriptor)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Device will only be closed the last time it is accessed */
|
/* The Device will only be closed the last time it is accessed */
|
||||||
if ((device->ref_count == 1) && (device->ops->close != NULL))
|
if ((device->ref_count == 1) && (device->ops->close != NULL))
|
||||||
{
|
{
|
||||||
ret = device->ops->close(device);
|
ret = device->ops->close(device);
|
||||||
@@ -651,7 +679,7 @@ static ssize_t _device_write(int descriptor, const void *buf, size_t count)
|
|||||||
/* Get the position */
|
/* Get the position */
|
||||||
pos = _descriptor_map[descriptor].pos;
|
pos = _descriptor_map[descriptor].pos;
|
||||||
|
|
||||||
/* Async or sync write */
|
/* Async or sync writes */
|
||||||
if (_descriptor_flags_is_valid(descriptor, MR_FLAG_WRONLY_ASYNC) == true)
|
if (_descriptor_flags_is_valid(descriptor, MR_FLAG_WRONLY_ASYNC) == true)
|
||||||
{
|
{
|
||||||
/* Async write */
|
/* Async write */
|
||||||
|
|||||||
Reference in New Issue
Block a user