source: rtems/cpukit/include/rtems/media.h @ 0fb724a

5
Last change on this file since 0fb724a was a59a6182, checked in by Sebastian Huber <sebastian.huber@…>, on 01/02/18 at 15:47:14

libblock: Use self-contained mutex for media

Update #2843.

  • Property mode set to 100644
File size: 13.7 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSMedia
5 *
6 * @brief Media API.
7 */
8
9/*
10 * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#ifndef RTEMS_MEDIA_H
24#define RTEMS_MEDIA_H
25
26#include <rtems.h>
27
28#ifdef __cplusplus
29extern "C" {
30#endif /* __cplusplus */
31
32/**
33 * @defgroup RTEMSMedia Media Manager
34 *
35 * @brief Removable media support.
36 *
37 * The media manager may be used to maintain the life cycle of a removable
38 * media.  Currently only disk devices are supported.  The initiator posts an
39 * event to the media manager and it will respond with appropriate default
40 * actions.  For example a disk attach will lead to inspection of the partition
41 * table and mounted file systems.  Clients can register listeners to react to
42 * events.
43 */
44/**@{**/
45
46#define RTEMS_MEDIA_MOUNT_BASE "/media"
47
48#define RTEMS_MEDIA_DELIMITER '-'
49
50/**
51 * Disk life cycle events:
52 * @dot
53 *   digraph disk_events {
54 *     "DISK ATTACH" -> "PARTITION INQUIRY";
55 *     "DISK ATTACH" -> "MOUNT";
56 *     "PARTITION INQUIRY" -> "PARTITION ATTACH";
57 *     "PARTITION INQUIRY" -> "DISK DETACH";
58 *     "PARTITION ATTACH" -> "MOUNT";
59 *     "MOUNT" -> "UNMOUNT";
60 *     "UNMOUNT" -> "PARTITION DETACH";
61 *     "UNMOUNT" -> "DISK DETACH";
62 *     "PARTITION DETACH" -> "DISK DETACH";
63 *   }
64 * @enddot
65 */
66typedef enum {
67  RTEMS_MEDIA_EVENT_DISK_ATTACH,
68  RTEMS_MEDIA_EVENT_DISK_DETACH,
69  RTEMS_MEDIA_EVENT_MOUNT,
70  RTEMS_MEDIA_EVENT_UNMOUNT,
71  RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
72  RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
73  RTEMS_MEDIA_EVENT_PARTITION_DETACH,
74  RTEMS_MEDIA_EVENT_ERROR
75} rtems_media_event;
76
77/**
78 * Normal state transition:
79 * @dot
80 *   digraph state {
81 *     INQUIRY -> READY [label="all listeners\nreturned successful"];
82 *     INQUIRY -> ABORTED [label="otherwise"];
83 *     READY -> SUCCESS [label="the worker\nreturned successful"];
84 *     READY -> FAILED [label="otherwise"];
85 *   }
86 * @enddot
87 */
88typedef enum {
89  RTEMS_MEDIA_STATE_INQUIRY,
90  RTEMS_MEDIA_STATE_READY,
91  RTEMS_MEDIA_STATE_ABORTED,
92  RTEMS_MEDIA_STATE_SUCCESS,
93  RTEMS_MEDIA_STATE_FAILED,
94  RTEMS_MEDIA_ERROR_DISK_UNKNOWN,
95  RTEMS_MEDIA_ERROR_DISK_EXISTS,
96  RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN,
97  RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS,
98  RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN,
99  RTEMS_MEDIA_ERROR_PARTITION_ORPHAN,
100  RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT,
101  RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK,
102  RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN,
103  RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS,
104  RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN
105} rtems_media_state;
106
107/**
108 * @brief Event listener.
109 *
110 * The listener will be called with the @a listener_arg passed to
111 * rtems_media_listener_add().
112 *
113 * Source and destination values for each event and state:
114 * <table>
115 *   <tr><th>Event</th><th>State</th><th>Source</th><th>Destination</th></tr>
116 *   <tr>
117 *     <td rowspan="5">RTEMS_MEDIA_EVENT_DISK_ATTACH</td>
118 *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>driver name</td><td>NULL</td>
119 *   </tr>
120 *   <tr>
121 *     <td>RTEMS_MEDIA_STATE_READY</td><td>driver name</td><td>NULL</td>
122 *   </tr>
123 *   <tr>
124 *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>driver name</td><td>NULL</td>
125 *   </tr>
126 *   <tr>
127 *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>driver name</td><td>disk path</td>
128 *   </tr>
129 *   <tr>
130 *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>driver name</td><td>NULL</td>
131 *   </tr>
132 *   <tr>
133 *     <td rowspan="5">RTEMS_MEDIA_EVENT_DISK_DETACH</td>
134 *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
135 *   </tr>
136 *   <tr>
137 *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
138 *   </tr>
139 *   <tr>
140 *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
141 *   </tr>
142 *   <tr>
143 *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>disk path</td><td>NULL</td>
144 *   </tr>
145 *   <tr>
146 *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
147 *   </tr>
148 *   <tr>
149 *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_INQUIRY</td>
150 *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
151 *   </tr>
152 *   <tr>
153 *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
154 *   </tr>
155 *   <tr>
156 *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
157 *   </tr>
158 *   <tr>
159 *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>disk path</td><td>NULL</td>
160 *   </tr>
161 *   <tr>
162 *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
163 *   </tr>
164 *   <tr>
165 *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_ATTACH</td>
166 *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>disk path</td><td>NULL</td>
167 *   </tr>
168 *   <tr>
169 *     <td>RTEMS_MEDIA_STATE_READY</td><td>disk path</td><td>NULL</td>
170 *   </tr>
171 *   <tr>
172 *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>disk path</td><td>NULL</td>
173 *   </tr>
174 *   <tr>
175 *     <td>RTEMS_MEDIA_STATE_SUCCESS</td>
176 *     <td>disk path</td><td>partition path</td>
177 *   </tr>
178 *   <tr>
179 *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>disk path</td><td>NULL</td>
180 *   </tr>
181 *   <tr>
182 *     <td rowspan="5">RTEMS_MEDIA_EVENT_PARTITION_DETACH</td>
183 *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>partition path</td><td>NULL</td>
184 *   </tr>
185 *   <tr>
186 *     <td>RTEMS_MEDIA_STATE_READY</td><td>partition path</td><td>NULL</td>
187 *   </tr>
188 *   <tr>
189 *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>partition path</td><td>NULL</td>
190 *   </tr>
191 *   <tr>
192 *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>partition path</td><td>NULL</td>
193 *   </tr>
194 *   <tr>
195 *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>partition path</td><td>NULL</td>
196 *   </tr>
197 *   <tr>
198 *     <td rowspan="5">RTEMS_MEDIA_EVENT_MOUNT</td>
199 *     <td>RTEMS_MEDIA_STATE_INQUIRY</td>
200 *     <td>disk or partition path</td><td>NULL</td>
201 *   </tr>
202 *   <tr>
203 *     <td>RTEMS_MEDIA_STATE_READY</td>
204 *     <td>disk or partition path</td><td>NULL</td>
205 *   </tr>
206 *   <tr>
207 *     <td>RTEMS_MEDIA_STATE_ABORTED</td>
208 *     <td>disk or partition path</td><td>NULL</td>
209 *   </tr>
210 *   <tr>
211 *     <td>RTEMS_MEDIA_STATE_SUCCESS</td>
212 *     <td>disk or partition path</td><td>mount path</td>
213 *   </tr>
214 *   <tr>
215 *     <td>RTEMS_MEDIA_STATE_FAILED</td>
216 *     <td>disk or partition path</td><td>NULL</td>
217 *   </tr>
218 *   <tr>
219 *     <td rowspan="5">RTEMS_MEDIA_EVENT_UNMOUNT</td>
220 *     <td>RTEMS_MEDIA_STATE_INQUIRY</td><td>mount path</td><td>NULL</td>
221 *   </tr>
222 *   <tr>
223 *     <td>RTEMS_MEDIA_STATE_READY</td><td>mount path</td><td>NULL</td>
224 *   </tr>
225 *   <tr>
226 *     <td>RTEMS_MEDIA_STATE_ABORTED</td><td>mount path</td><td>NULL</td>
227 *   </tr>
228 *   <tr>
229 *     <td>RTEMS_MEDIA_STATE_SUCCESS</td><td>mount path</td><td>NULL</td>
230 *   </tr>
231 *   <tr>
232 *     <td>RTEMS_MEDIA_STATE_FAILED</td><td>mount path</td><td>NULL</td>
233 *   </tr>
234 *   <tr>
235 *     <td rowspan="11">RTEMS_MEDIA_EVENT_ERROR</td>
236 *     <td>RTEMS_MEDIA_ERROR_DISK_UNKNOWN</td><td>disk path</td><td>NULL</td>
237 *   </tr>
238 *   <tr>
239 *     <td>RTEMS_MEDIA_ERROR_DISK_EXISTS</td><td>disk path</td><td>NULL</td>
240 *   </tr>
241 *   <tr>
242 *     <td>RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN</td>
243 *     <td>disk or partition path</td><td>NULL</td>
244 *   </tr>
245 *   <tr>
246 *     <td>RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS</td>
247 *     <td>disk or partition path</td><td>NULL</td>
248 *   </tr>
249 *   <tr>
250 *     <td>RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN</td>
251 *     <td>partition path</td><td>NULL</td>
252 *   </tr>
253 *   <tr>
254 *     <td>RTEMS_MEDIA_ERROR_PARTITION_ORPHAN</td>
255 *     <td>partition path</td><td>disk path</td>
256 *   </tr>
257 *   <tr>
258 *     <td>RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT</td>
259 *     <td>partition path</td><td>mount path</td>
260 *   </tr>
261 *   <tr>
262 *     <td>RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK</td>
263 *     <td>partition path</td><td>disk path</td>
264 *   </tr>
265 *   <tr>
266 *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN</td>
267 *     <td>mount path</td><td>NULL</td>
268 *   </tr>
269 *   <tr>
270 *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS</td>
271 *     <td>mount path</td><td>NULL</td>
272 *   </tr>
273 *   <tr>
274 *     <td>RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN</td>
275 *     <td>mount path</td><td>disk path</td>
276 *   </tr>
277 * </table>
278 *
279 * @retval RTEMS_SUCCESSFUL Successful operation.
280 * @retval RTEMS_IO_ERROR In the inquiry state this will abort the action.
281 */
282typedef rtems_status_code (*rtems_media_listener)(
283  rtems_media_event event,
284  rtems_media_state state,
285  const char *src,
286  const char *dest,
287  void *listener_arg
288);
289
290/**
291 * @brief Do the work corresponding to an event.
292 *
293 * The @a state will be
294 * - RTEMS_MEDIA_STATE_READY, or
295 * - RTEMS_MEDIA_STATE_ABORTED.
296 *
297 * It will be called with the @a src and @a worker_arg arguments passed to
298 * rtems_media_post_event().
299 *
300 * The destination shall be returned in @a dest in case of success.  It shall
301 * be allocated with malloc().
302 *
303 * @retval RTEMS_SUCCESSFUL Successful operation.
304 * @retval RTEMS_IO_ERROR Failure.
305 */
306typedef rtems_status_code (*rtems_media_worker)(
307  rtems_media_state state,
308  const char *src,
309  char **dest,
310  void *worker_arg
311);
312
313/**
314 * @name Base
315 */
316/**@{**/
317
318/**
319 * @brief Initializes the media manager.
320 *
321 * Calling this function more than once will have no effects.  There is no
322 * protection against concurrent access.
323 *
324 * @retval RTEMS_SUCCESSFUL Successful operation.
325 * @retval RTEMS_NO_MEMORY Not enough resources.
326 */
327RTEMS_INLINE_ROUTINE rtems_status_code rtems_media_initialize(void)
328{
329  return RTEMS_SUCCESSFUL;
330}
331
332/**
333 * @brief Adds the @a listener with argument @a listener_arg.
334 *
335 * @retval RTEMS_SUCCESSFUL Successful operation.
336 * @retval RTEMS_NO_MEMORY Not enough memory.
337 * @retval RTEMS_TOO_MANY Such a listener is already present.
338 */
339rtems_status_code rtems_media_listener_add(
340  rtems_media_listener listener,
341  void *listener_arg
342);
343
344/**
345 * @brief Removes the @a listener with argument @a listener_arg.
346 *
347 * @retval RTEMS_SUCCESSFUL Successful operation.
348 * @retval RTEMS_INVALID_ID No such listener is present.
349 */
350rtems_status_code rtems_media_listener_remove(
351  rtems_media_listener listener,
352  void *listener_arg
353);
354
355/**
356 * @brief Posts the @a event with source @a src.
357 *
358 * The @a worker will be called with the @a worker_arg argument.
359 *
360 * The destination will be returned in @a dest in case of success.  It will be
361 * allocated with malloc() and should be freed if not needed anymore.
362 *
363 * The work will be done by the calling thread.  You can avoid this if you use
364 * the media server via rtems_media_server_post_event().
365 *
366 * @retval RTEMS_SUCCESSFUL Successful operation.
367 * @retval RTEMS_UNSATISFIED One or more listeners aborted the action.
368 * @retval RTEMS_IO_ERROR The worker returned with an error status.
369 */
370rtems_status_code rtems_media_post_event(
371  rtems_media_event event,
372  const char *src,
373  char **dest,
374  rtems_media_worker worker,
375  void *worker_arg
376);
377
378/** @} */
379
380/**
381 * @name Server
382 */
383/**@{**/
384
385/**
386 * @brief Initializes the media manager and media server.
387 *
388 * It creates a server task with the @a priority, @a stack_size, @a modes, and
389 * @a attributes parameters.
390 *
391 * Calling this function more than once will have no effects.  There is no
392 * protection against concurrent access.
393 *
394 * @retval RTEMS_SUCCESSFUL Successful operation.
395 * @retval RTEMS_NO_MEMORY Not enough resources.
396 */
397rtems_status_code rtems_media_server_initialize(
398  rtems_task_priority priority,
399  size_t stack_size,
400  rtems_mode modes,
401  rtems_attribute attributes
402);
403
404/**
405 * @brief Sends an event message to the media server.
406 *
407 * @see See rtems_media_post_event().
408 *
409 * @retval RTEMS_SUCCESSFUL Successful operation.
410 * @retval RTEMS_NO_MEMORY Not enough resources to notify the media server.
411 * @retval RTEMS_NOT_CONFIGURED Media server is not initialized.
412 */
413rtems_status_code rtems_media_server_post_event(
414  rtems_media_event event,
415  const char *src,
416  rtems_media_worker worker,
417  void *worker_arg
418);
419
420/**
421 * @brief See rtems_media_server_post_event().
422 */
423static inline rtems_status_code rtems_media_server_disk_attach(
424  const char *driver_name,
425  rtems_media_worker worker,
426  void *worker_arg
427)
428{
429  return rtems_media_server_post_event(
430    RTEMS_MEDIA_EVENT_DISK_ATTACH,
431    driver_name,
432    worker,
433    worker_arg
434  );
435}
436
437/**
438 * @brief See rtems_media_server_post_event().
439 */
440static inline rtems_status_code rtems_media_server_disk_detach(
441  const char *disk_path
442)
443{
444  return rtems_media_server_post_event(
445    RTEMS_MEDIA_EVENT_DISK_DETACH,
446    disk_path,
447    NULL,
448    NULL
449  );
450}
451
452/** @} */
453
454/**
455 * @name Path Construction
456 */
457/**@{**/
458
459/**
460 * @brief Creates a new path as "prefix/name-major".
461 *
462 * @return New string, or @c NULL if no memory is available.
463 */
464char *rtems_media_create_path(
465  const char *prefix,
466  const char *name,
467  rtems_device_major_number major
468);
469
470/**
471 * @brief Replaces the prefix of the @a path with @a new_prefix.
472 *
473 * The prefix is everything up to the last '/'.
474 *
475 * @return New string, or @c NULL if no memory is available.
476 */
477char *rtems_media_replace_prefix(const char *new_prefix, const char *path);
478
479/**
480 * @brief Appends the @a minor number to the @a path resulting in "path-minor".
481 *
482 * @return New string, or @c NULL if no memory is available.
483 */
484char *rtems_media_append_minor(
485  const char *path,
486  rtems_device_minor_number minor
487);
488
489/** @} */
490
491/**
492 * @name Support
493 */
494/**@{**/
495
496/**
497 * @brief Returns the device identifier for the device located at
498 * @a device_path in @a device_identifier.
499 *
500 * @retval RTEMS_SUCCESSFUL Successful operation.
501 * @retval RTEMS_INVALID_ID No device at this path.
502 */
503rtems_status_code rtems_media_get_device_identifier(
504  const char *device_path,
505  dev_t *device_identifier
506);
507
508const char *rtems_media_event_description(rtems_media_event event);
509
510const char *rtems_media_state_description(rtems_media_state state);
511
512/** @} */
513
514/** @} */
515
516#ifdef __cplusplus
517}
518#endif /* __cplusplus */
519
520#endif /* RTEMS_MEDIA_H */
Note: See TracBrowser for help on using the repository browser.