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

4.115
Last change on this file since d91e3a7 was d91e3a7, checked in by Sebastian Huber <sebastian.huber@…>, on 08/13/10 at 12:40:16

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

  • libblock/include/rtems/media.h, libblock/src/media-desc.c, libblock/src/media-dev-ident.c, libblock/src/media-path.c, libblock/src/media-server.c, libblock/src/media.c: New files.
  • Makefile.am, preinstall.am, libblock/Makefile.am: Reflect changes above.
  • Property mode set to 100644
File size: 13.8 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 * A message queue will be used for communication with the server task which
391 * may buffer up to @a message_count messages.
392 *
393 * Calling this function more than once will have no effects.  There is no
394 * protection against concurrent access.
395 *
396 * @retval RTEMS_SUCCESSFUL Successful operation.
397 * @retval RTEMS_NO_MEMORY Not enough resources.
398 */
399rtems_status_code rtems_media_server_initialize(
400  rtems_task_priority priority,
401  size_t stack_size,
402  rtems_mode modes,
403  rtems_attribute attributes,
404  uint32_t message_count
405);
406
407/**
408 * @brief Sends an event message to the media server.
409 *
410 * @see See rtems_media_post_event().
411 *
412 * @retval RTEMS_SUCCESSFUL Successful operation.
413 * @retval RTEMS_UNSATISFIED Message queue is full.
414 * @retval RTEMS_NO_MEMORY Not enough memory for the message.
415 */
416rtems_status_code rtems_media_server_post_event(
417  rtems_media_event event,
418  const char *src,
419  rtems_media_worker worker,
420  void *worker_arg
421);
422
423/**
424 * @brief See rtems_media_server_post_event().
425 */
426static inline rtems_status_code rtems_media_server_disk_attach(
427  const char *driver_name,
428  rtems_media_worker worker,
429  void *worker_arg
430)
431{
432  return rtems_media_server_post_event(
433    RTEMS_MEDIA_EVENT_DISK_ATTACH,
434    driver_name,
435    worker,
436    worker_arg
437  );
438}
439
440/**
441 * @brief See rtems_media_server_post_event().
442 */
443static inline rtems_status_code rtems_media_server_disk_detach(
444  const char *disk_path
445)
446{
447  return rtems_media_server_post_event(
448    RTEMS_MEDIA_EVENT_DISK_DETACH,
449    disk_path,
450    NULL,
451    NULL
452  );
453}
454
455/** @} */
456
457/**
458 * @name Path Construction
459 *
460 * @{
461 */
462
463/**
464 * @brief Creates a new path as "prefix/name-major".
465 *
466 * @return New string, or @c NULL if no memory is available.
467 */
468char *rtems_media_create_path(
469  const char *prefix,
470  const char *name,
471  rtems_device_major_number major
472);
473
474/**
475 * @brief Replaces the prefix of the @a path with @a new_prefix.
476 *
477 * The prefix is everything up to the last '/'.
478 *
479 * @return New string, or @c NULL if no memory is available.
480 */
481char *rtems_media_replace_prefix(const char *new_prefix, const char *path);
482
483/**
484 * @brief Appends the @a minor number to the @a path resulting in "path-minor".
485 *
486 * @return New string, or @c NULL if no memory is available.
487 */
488char *rtems_media_append_minor(
489  const char *path,
490  rtems_device_minor_number minor
491);
492
493/** @} */
494
495/**
496 * @name Support
497 *
498 * @{
499 */
500
501/**
502 * @brief Returns the device identifier for the device located at
503 * @a device_path in @a device_identifier.
504 *
505 * @retval RTEMS_SUCCESSFUL Successful operation.
506 * @retval RTEMS_INVALID_ID No device at this path.
507 */
508rtems_status_code rtems_media_get_device_identifier(
509  const char *device_path,
510  dev_t *device_identifier
511);
512
513const char *rtems_media_event_description(rtems_media_event event);
514
515const char *rtems_media_state_description(rtems_media_state state);
516
517/** @} */
518
519/** @} */
520
521#ifdef __cplusplus
522}
523#endif /* __cplusplus */
524
525#endif /* RTEMS_MEDIA_H */
Note: See TracBrowser for help on using the repository browser.