Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSIOMedia
0007  *
0008  * @brief Media Manager API.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2009, 2018 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifndef RTEMS_MEDIA_H
0037 #define RTEMS_MEDIA_H
0038 
0039 #include <sys/types.h>
0040 #include <rtems.h>
0041 
0042 #ifdef __cplusplus
0043 extern "C" {
0044 #endif /* __cplusplus */
0045 
0046 /**
0047  * @defgroup RTEMSIOMedia Media Manager
0048  *
0049  * @ingroup LibIO
0050  *
0051  * @brief Removable media support.
0052  *
0053  * The media manager may be used to maintain the life cycle of a removable
0054  * media.  Currently only disk devices are supported.  The initiator posts an
0055  * event to the media manager and it will respond with appropriate default
0056  * actions.  For example a disk attach will lead to inspection of the partition
0057  * table and mounted file systems.  Clients can register listeners to react to
0058  * events.
0059  */
0060 /**@{**/
0061 
0062 #define RTEMS_MEDIA_MOUNT_BASE "/media"
0063 
0064 #define RTEMS_MEDIA_DELIMITER '-'
0065 
0066 /**
0067  * Disk life cycle events:
0068  * @dot
0069  *   digraph disk_events {
0070  *     "DISK ATTACH" -> "PARTITION INQUIRY";
0071  *     "DISK ATTACH" -> "MOUNT";
0072  *     "PARTITION INQUIRY" -> "PARTITION ATTACH";
0073  *     "PARTITION INQUIRY" -> "DISK DETACH";
0074  *     "PARTITION ATTACH" -> "MOUNT";
0075  *     "MOUNT" -> "UNMOUNT";
0076  *     "UNMOUNT" -> "PARTITION DETACH";
0077  *     "UNMOUNT" -> "DISK DETACH";
0078  *     "PARTITION DETACH" -> "DISK DETACH";
0079  *   }
0080  * @enddot
0081  */
0082 typedef enum {
0083   RTEMS_MEDIA_EVENT_DISK_ATTACH,
0084   RTEMS_MEDIA_EVENT_DISK_DETACH,
0085   RTEMS_MEDIA_EVENT_MOUNT,
0086   RTEMS_MEDIA_EVENT_UNMOUNT,
0087   RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
0088   RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
0089   RTEMS_MEDIA_EVENT_PARTITION_DETACH,
0090   RTEMS_MEDIA_EVENT_ERROR
0091 } rtems_media_event;
0092 
0093 /**
0094  * Normal state transition:
0095  * @dot
0096  *   digraph state {
0097  *     INQUIRY -> READY [label="all listeners\nreturned successful"];
0098  *     INQUIRY -> ABORTED [label="otherwise"];
0099  *     READY -> SUCCESS [label="the worker\nreturned successful"];
0100  *     READY -> FAILED [label="otherwise"];
0101  *   }
0102  * @enddot
0103  */
0104 typedef enum {
0105   RTEMS_MEDIA_STATE_INQUIRY,
0106   RTEMS_MEDIA_STATE_READY,
0107   RTEMS_MEDIA_STATE_ABORTED,
0108   RTEMS_MEDIA_STATE_SUCCESS,
0109   RTEMS_MEDIA_STATE_FAILED,
0110   RTEMS_MEDIA_ERROR_DISK_UNKNOWN,
0111   RTEMS_MEDIA_ERROR_DISK_EXISTS,
0112   RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN,
0113   RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS,
0114   RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN,
0115   RTEMS_MEDIA_ERROR_PARTITION_ORPHAN,
0116   RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT,
0117   RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK,
0118   RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN,
0119   RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS,
0120   RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN
0121 } rtems_media_state;
0122 
0123 /**
0124  * @brief Event listener.
0125  *
0126  * The listener will be called with the @a listener_arg passed to
0127  * rtems_media_listener_add().
0128  *
0129  * Source and destination values for each event and state:
0130  * <table>
0131  *   <tr><th>Event</th><th>State</th><th>Source</th><th>Destination</th></tr>
0132  *   <tr>
0133  *     <td rowspan="5">RTEMS_MEDIA_EVENT_DISK_ATTACH</td>
0134  *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>driver name</td><td>NULL</td>
0135  *   </tr>
0136  *   <tr>
0137  *     <td>RTEMS_MEDIA_STATE_READY</td><td>driver name</td><td>NULL</td>
0138  *   </tr>
0139  *   <tr>
0140  *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>driver name</td><td>NULL</td>
0141  *   </tr>
0142  *   <tr>
0143  *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>driver name</td><td>disk path</td>
0144  *   </tr>
0145  *   <tr>
0146  *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>driver name</td><td>NULL</td>
0147  *   </tr>
0148  *   <tr>
0149  *     <td rowspan="5">RTEMS_MEDIA_EVENT_DISK_DETACH</td>
0150  *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
0151  *   </tr>
0152  *   <tr>
0153  *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
0154  *   </tr>
0155  *   <tr>
0156  *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
0157  *   </tr>
0158  *   <tr>
0159  *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>disk path</td><td>NULL</td>
0160  *   </tr>
0161  *   <tr>
0162  *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
0163  *   </tr>
0164  *   <tr>
0165  *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_INQUIRY</td>
0166  *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
0167  *   </tr>
0168  *   <tr>
0169  *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
0170  *   </tr>
0171  *   <tr>
0172  *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
0173  *   </tr>
0174  *   <tr>
0175  *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>disk path</td><td>NULL</td>
0176  *   </tr>
0177  *   <tr>
0178  *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
0179  *   </tr>
0180  *   <tr>
0181  *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_ATTACH</td>
0182  *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
0183  *   </tr>
0184  *   <tr>
0185  *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
0186  *   </tr>
0187  *   <tr>
0188  *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
0189  *   </tr>
0190  *   <tr>
0191  *     <td>RTEMS_MEDIA_STATE_SUCCESS</td>
0192  *     <td>disk path</td><td>partition path</td>
0193  *   </tr>
0194  *   <tr>
0195  *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
0196  *   </tr>
0197  *   <tr>
0198  *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_DETACH</td>
0199  *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>partition path</td><td>NULL</td>
0200  *   </tr>
0201  *   <tr>
0202  *     <td>RTEMS_MEDIA_STATE_READY</td><td>partition path</td><td>NULL</td>
0203  *   </tr>
0204  *   <tr>
0205  *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>partition path</td><td>NULL</td>
0206  *   </tr>
0207  *   <tr>
0208  *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>partition path</td><td>NULL</td>
0209  *   </tr>
0210  *   <tr>
0211  *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>partition path</td><td>NULL</td>
0212  *   </tr>
0213  *   <tr>
0214  *     <td rowspan="5">RTEMS_MEDIA_EVENT_MOUNT</td>
0215  *     <td>RTEMS_MEDIA_STATE_INQUIRY</td>
0216  *     <td>disk or partition path</td><td>NULL</td>
0217  *   </tr>
0218  *   <tr>
0219  *     <td>RTEMS_MEDIA_STATE_READY</td>
0220  *     <td>disk or partition path</td><td>NULL</td>
0221  *   </tr>
0222  *   <tr>
0223  *     <td>RTEMS_MEDIA_STATE_ABORTED</td>
0224  *     <td>disk or partition path</td><td>NULL</td>
0225  *   </tr>
0226  *   <tr>
0227  *     <td>RTEMS_MEDIA_STATE_SUCCESS</td>
0228  *     <td>disk or partition path</td><td>mount path</td>
0229  *   </tr>
0230  *   <tr>
0231  *     <td>RTEMS_MEDIA_STATE_FAILED</td>
0232  *     <td>disk or partition path</td><td>NULL</td>
0233  *   </tr>
0234  *   <tr>
0235  *     <td rowspan="5">RTEMS_MEDIA_EVENT_UNMOUNT</td>
0236  *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>mount path</td><td>NULL</td>
0237  *   </tr>
0238  *   <tr>
0239  *     <td>RTEMS_MEDIA_STATE_READY</td><td>mount path</td><td>NULL</td>
0240  *   </tr>
0241  *   <tr>
0242  *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>mount path</td><td>NULL</td>
0243  *   </tr>
0244  *   <tr>
0245  *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>mount path</td><td>NULL</td>
0246  *   </tr>
0247  *   <tr>
0248  *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>mount path</td><td>NULL</td>
0249  *   </tr>
0250  *   <tr>
0251  *     <td rowspan="11">RTEMS_MEDIA_EVENT_ERROR</td>
0252  *     <td>RTEMS_MEDIA_ERROR_DISK_UNKNOWN</td><td>disk path</td><td>NULL</td>
0253  *   </tr>
0254  *   <tr>
0255  *     <td>RTEMS_MEDIA_ERROR_DISK_EXISTS</td><td>disk path</td><td>NULL</td>
0256  *   </tr>
0257  *   <tr>
0258  *     <td>RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN</td>
0259  *     <td>disk or partition path</td><td>NULL</td>
0260  *   </tr>
0261  *   <tr>
0262  *     <td>RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS</td>
0263  *     <td>disk or partition path</td><td>NULL</td>
0264  *   </tr>
0265  *   <tr>
0266  *     <td>RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN</td>
0267  *     <td>partition path</td><td>NULL</td>
0268  *   </tr>
0269  *   <tr>
0270  *     <td>RTEMS_MEDIA_ERROR_PARTITION_ORPHAN</td>
0271  *     <td>partition path</td><td>disk path</td>
0272  *   </tr>
0273  *   <tr>
0274  *     <td>RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT</td>
0275  *     <td>partition path</td><td>mount path</td>
0276  *   </tr>
0277  *   <tr>
0278  *     <td>RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK</td>
0279  *     <td>partition path</td><td>disk path</td>
0280  *   </tr>
0281  *   <tr>
0282  *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN</td>
0283  *     <td>mount path</td><td>NULL</td>
0284  *   </tr>
0285  *   <tr>
0286  *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS</td>
0287  *     <td>mount path</td><td>NULL</td>
0288  *   </tr>
0289  *   <tr>
0290  *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN</td>
0291  *     <td>mount path</td><td>disk path</td>
0292  *   </tr>
0293  * </table>
0294  *
0295  * @retval RTEMS_SUCCESSFUL Successful operation.
0296  * @retval RTEMS_IO_ERROR In the inquiry state this will abort the action.
0297  * @retval RTEMS_INCORRECT_STATE In the failed state this will cause a retry.
0298  * Make sure to have a retry counter or similar to avoid endless loops if you
0299  * use this value.
0300  */
0301 typedef rtems_status_code (*rtems_media_listener)(
0302   rtems_media_event event,
0303   rtems_media_state state,
0304   const char *src,
0305   const char *dest,
0306   void *listener_arg
0307 );
0308 
0309 /**
0310  * @brief Do the work corresponding to an event.
0311  *
0312  * The @a state will be
0313  * - RTEMS_MEDIA_STATE_READY, or
0314  * - RTEMS_MEDIA_STATE_ABORTED.
0315  *
0316  * It will be called with the @a src and @a worker_arg arguments passed to
0317  * rtems_media_post_event().
0318  *
0319  * The destination shall be returned in @a dest in case of success.  It shall
0320  * be allocated with malloc().
0321  *
0322  * @retval RTEMS_SUCCESSFUL Successful operation.
0323  * @retval RTEMS_IO_ERROR Failure.
0324  */
0325 typedef rtems_status_code (*rtems_media_worker)(
0326   rtems_media_state state,
0327   const char *src,
0328   char **dest,
0329   void *worker_arg
0330 );
0331 
0332 /**
0333  * @name Base
0334  */
0335 /**@{**/
0336 
0337 /**
0338  * @brief Initializes the media manager.
0339  *
0340  * Calling this function more than once will have no effects.  There is no
0341  * protection against concurrent access.
0342  *
0343  * @retval RTEMS_SUCCESSFUL Successful operation.
0344  * @retval RTEMS_NO_MEMORY Not enough resources.
0345  */
0346 static inline rtems_status_code rtems_media_initialize(void)
0347 {
0348   return RTEMS_SUCCESSFUL;
0349 }
0350 
0351 /**
0352  * @brief Adds the @a listener with argument @a listener_arg.
0353  *
0354  * @retval RTEMS_SUCCESSFUL Successful operation.
0355  * @retval RTEMS_NO_MEMORY Not enough memory.
0356  * @retval RTEMS_TOO_MANY Such a listener is already present.
0357  */
0358 rtems_status_code rtems_media_listener_add(
0359   rtems_media_listener listener,
0360   void *listener_arg
0361 );
0362 
0363 /**
0364  * @brief Removes the @a listener with argument @a listener_arg.
0365  *
0366  * @retval RTEMS_SUCCESSFUL Successful operation.
0367  * @retval RTEMS_INVALID_ID No such listener is present.
0368  */
0369 rtems_status_code rtems_media_listener_remove(
0370   rtems_media_listener listener,
0371   void *listener_arg
0372 );
0373 
0374 /**
0375  * @brief Posts the @a event with source @a src.
0376  *
0377  * The @a worker will be called with the @a worker_arg argument.
0378  *
0379  * The destination will be returned in @a dest in case of success.  It will be
0380  * allocated with malloc() and should be freed if not needed anymore.
0381  *
0382  * The work will be done by the calling thread.  You can avoid this if you use
0383  * the media server via rtems_media_server_post_event().
0384  *
0385  * @retval RTEMS_SUCCESSFUL Successful operation.
0386  * @retval RTEMS_UNSATISFIED One or more listeners aborted the action.
0387  * @retval RTEMS_IO_ERROR The worker returned with an error status.
0388  */
0389 rtems_status_code rtems_media_post_event(
0390   rtems_media_event event,
0391   const char *src,
0392   char **dest,
0393   rtems_media_worker worker,
0394   void *worker_arg
0395 );
0396 
0397 /** @} */
0398 
0399 /**
0400  * @name Server
0401  */
0402 /**@{**/
0403 
0404 /**
0405  * @brief Initializes the media manager and media server.
0406  *
0407  * It creates a server task with the @a priority, @a stack_size, @a modes, and
0408  * @a attributes parameters.
0409  *
0410  * Calling this function more than once will have no effects.  There is no
0411  * protection against concurrent access.
0412  *
0413  * @retval RTEMS_SUCCESSFUL Successful operation.
0414  * @retval RTEMS_NO_MEMORY Not enough resources.
0415  */
0416 rtems_status_code rtems_media_server_initialize(
0417   rtems_task_priority priority,
0418   size_t stack_size,
0419   rtems_mode modes,
0420   rtems_attribute attributes
0421 );
0422 
0423 /**
0424  * @brief Sends an event message to the media server.
0425  *
0426  * @see See rtems_media_post_event().
0427  *
0428  * @retval RTEMS_SUCCESSFUL Successful operation.
0429  * @retval RTEMS_NO_MEMORY Not enough resources to notify the media server.
0430  * @retval RTEMS_NOT_CONFIGURED Media server is not initialized.
0431  */
0432 rtems_status_code rtems_media_server_post_event(
0433   rtems_media_event event,
0434   const char *src,
0435   rtems_media_worker worker,
0436   void *worker_arg
0437 );
0438 
0439 /**
0440  * @brief See rtems_media_server_post_event().
0441  */
0442 static inline rtems_status_code rtems_media_server_disk_attach(
0443   const char *driver_name,
0444   rtems_media_worker worker,
0445   void *worker_arg
0446 )
0447 {
0448   return rtems_media_server_post_event(
0449     RTEMS_MEDIA_EVENT_DISK_ATTACH,
0450     driver_name,
0451     worker,
0452     worker_arg
0453   );
0454 }
0455 
0456 /**
0457  * @brief See rtems_media_server_post_event().
0458  */
0459 static inline rtems_status_code rtems_media_server_disk_detach(
0460   const char *disk_path
0461 )
0462 {
0463   return rtems_media_server_post_event(
0464     RTEMS_MEDIA_EVENT_DISK_DETACH,
0465     disk_path,
0466     NULL,
0467     NULL
0468   );
0469 }
0470 
0471 /** @} */
0472 
0473 /**
0474  * @name Path Construction
0475  */
0476 /**@{**/
0477 
0478 /**
0479  * @brief Creates a new path as "prefix/name-major".
0480  *
0481  * @return New string, or @c NULL if no memory is available.
0482  */
0483 char *rtems_media_create_path(
0484   const char *prefix,
0485   const char *name,
0486   rtems_device_major_number major
0487 );
0488 
0489 /**
0490  * @brief Replaces the prefix of the @a path with @a new_prefix.
0491  *
0492  * The prefix is everything up to the last '/'.
0493  *
0494  * @return New string, or @c NULL if no memory is available.
0495  */
0496 char *rtems_media_replace_prefix(const char *new_prefix, const char *path);
0497 
0498 /**
0499  * @brief Appends the @a minor number to the @a path resulting in "path-minor".
0500  *
0501  * @return New string, or @c NULL if no memory is available.
0502  */
0503 char *rtems_media_append_minor(
0504   const char *path,
0505   rtems_device_minor_number minor
0506 );
0507 
0508 /** @} */
0509 
0510 /**
0511  * @name Support
0512  */
0513 /**@{**/
0514 
0515 /**
0516  * @brief Returns the device identifier for the device located at
0517  * @a device_path in @a device_identifier.
0518  *
0519  * @retval RTEMS_SUCCESSFUL Successful operation.
0520  * @retval RTEMS_INVALID_ID No device at this path.
0521  */
0522 rtems_status_code rtems_media_get_device_identifier(
0523   const char *device_path,
0524   dev_t *device_identifier
0525 );
0526 
0527 const char *rtems_media_event_description(rtems_media_event event);
0528 
0529 const char *rtems_media_state_description(rtems_media_state state);
0530 
0531 /** @} */
0532 
0533 /** @} */
0534 
0535 #ifdef __cplusplus
0536 }
0537 #endif /* __cplusplus */
0538 
0539 #endif /* RTEMS_MEDIA_H */