source: rtems/cpukit/libblock/include/rtems/media.h @ d4d6bd81

4.11
Last change on this file since d4d6bd81 was d4d6bd81, checked in by Sebastian Huber <sebastian.huber@…>, on Aug 25, 2010 at 8:44:14 AM

2010-08-25 Sebastian Huber <sebastian.huber@…>

  • libblock/include/rtems/media.h, libblock/src/media-server.c: Use chains instead of a message queue.
  • 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.com/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/**
320 * @brief Initializes the media manager.
321 *
322 * Calling this function more than once will have no effects.  There is no
323 * protection against concurrent access.
324 *
325 * @retval RTEMS_SUCCESSFUL Successful operation.
326 * @retval RTEMS_NO_MEMORY Not enough resources.
327 */
328rtems_status_code rtems_media_initialize(void);
329
330/**
331 * @brief Adds the @a listener with argument @a listener_arg.
332 *
333 * @retval RTEMS_SUCCESSFUL Successful operation.
334 * @retval RTEMS_NO_MEMORY Not enough memory.
335 * @retval RTEMS_TOO_MANY Such a listener is already present.
336 */
337rtems_status_code rtems_media_listener_add(
338  rtems_media_listener listener,
339  void *listener_arg
340);
341
342/**
343 * @brief Removes the @a listener with argument @a listener_arg.
344 *
345 * @retval RTEMS_SUCCESSFUL Successful operation.
346 * @retval RTEMS_INVALID_ID No such listener is present.
347 */
348rtems_status_code rtems_media_listener_remove(
349  rtems_media_listener listener,
350  void *listener_arg
351);
352
353/**
354 * @brief Posts the @a event with source @a src.
355 *
356 * The @a worker will be called with the @a worker_arg argument.
357 *
358 * The destination will be returned in @a dest in case of success.  It will be
359 * allocated with malloc() and should be freed if not needed anymore.
360 *
361 * The work will be done by the calling thread.  You can avoid this if you use
362 * the media server via rtems_media_server_post_event().
363 *
364 * @retval RTEMS_SUCCESSFUL Successful operation.
365 * @retval RTEMS_UNSATISFIED One or more listeners aborted the action.
366 * @retval RTEMS_IO_ERROR The worker returned with an error status.
367 */
368rtems_status_code rtems_media_post_event(
369  rtems_media_event event,
370  const char *src,
371  char **dest,
372  rtems_media_worker worker,
373  void *worker_arg
374);
375
376/** @} */
377
378/**
379 * @name Server
380 *
381 * @{
382 */
383
384/**
385 * @brief Initializes the media manager and media server.
386 *
387 * It creates a server task with the @a priority, @a stack_size, @a modes, and
388 * @a attributes parameters.
389 *
390 * Calling this function more than once will have no effects.  There is no
391 * protection against concurrent access.
392 *
393 * @retval RTEMS_SUCCESSFUL Successful operation.
394 * @retval RTEMS_NO_MEMORY Not enough resources.
395 */
396rtems_status_code rtems_media_server_initialize(
397  rtems_task_priority priority,
398  size_t stack_size,
399  rtems_mode modes,
400  rtems_attribute attributes
401);
402
403/**
404 * @brief Sends an event message to the media server.
405 *
406 * @see See rtems_media_post_event().
407 *
408 * @retval RTEMS_SUCCESSFUL Successful operation.
409 * @retval RTEMS_NO_MEMORY Not enough resources to notify the media server.
410 * @retval RTEMS_NOT_CONFIGURED Media server is not initialized.
411 */
412rtems_status_code rtems_media_server_post_event(
413  rtems_media_event event,
414  const char *src,
415  rtems_media_worker worker,
416  void *worker_arg
417);
418
419/**
420 * @brief See rtems_media_server_post_event().
421 */
422static inline rtems_status_code rtems_media_server_disk_attach(
423  const char *driver_name,
424  rtems_media_worker worker,
425  void *worker_arg
426)
427{
428  return rtems_media_server_post_event(
429    RTEMS_MEDIA_EVENT_DISK_ATTACH,
430    driver_name,
431    worker,
432    worker_arg
433  );
434}
435
436/**
437 * @brief See rtems_media_server_post_event().
438 */
439static inline rtems_status_code rtems_media_server_disk_detach(
440  const char *disk_path
441)
442{
443  return rtems_media_server_post_event(
444    RTEMS_MEDIA_EVENT_DISK_DETACH,
445    disk_path,
446    NULL,
447    NULL
448  );
449}
450
451/** @} */
452
453/**
454 * @name Path Construction
455 *
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/**
498 * @brief Returns the device identifier for the device located at
499 * @a device_path in @a device_identifier.
500 *
501 * @retval RTEMS_SUCCESSFUL Successful operation.
502 * @retval RTEMS_INVALID_ID No device at this path.
503 */
504rtems_status_code rtems_media_get_device_identifier(
505  const char *device_path,
506  dev_t *device_identifier
507);
508
509const char *rtems_media_event_description(rtems_media_event event);
510
511const char *rtems_media_state_description(rtems_media_state state);
512
513/** @} */
514
515/** @} */
516
517#ifdef __cplusplus
518}
519#endif /* __cplusplus */
520
521#endif /* RTEMS_MEDIA_H */
Note: See TracBrowser for help on using the repository browser.