µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
block-device.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2015-2025 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12#ifndef CMSIS_PLUS_POSIX_IO_BLOCK_DEVICE_H_
13#define CMSIS_PLUS_POSIX_IO_BLOCK_DEVICE_H_
14
15// ----------------------------------------------------------------------------
16
17#if defined(__cplusplus)
18
19// ----------------------------------------------------------------------------
20
21#if defined(OS_USE_OS_APP_CONFIG_H)
22#include <cmsis-plus/os-app-config.h>
23#endif
24
26
27// ----------------------------------------------------------------------------
28
29#pragma GCC diagnostic push
30#if defined(__clang__)
31#pragma clang diagnostic ignored "-Wc++98-compat"
32#endif
33
34// ----------------------------------------------------------------------------
35
36namespace os
37{
38 namespace posix
39 {
40 // ------------------------------------------------------------------------
41
42 class block_device_impl;
43
44 // ========================================================================
45
46 // TODO: add support to indicate that there is no media in drive.
47 // TODO: add support to indicate the media is write protected.
48
54#pragma GCC diagnostic push
55#if defined(__clang__)
56#elif defined(__GNUC__)
57#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
58#pragma GCC diagnostic ignored "-Wsuggest-final-types"
59#endif
60 class block_device : public device
61 {
62 // ----------------------------------------------------------------------
63
64 public:
65 using blknum_t = std::size_t;
66
67 // ----------------------------------------------------------------------
68
74 public:
76
81 // The rule of five.
82 block_device (const block_device&) = delete;
83 block_device (block_device&&) = delete;
85 operator= (const block_device&)
86 = delete;
88 operator= (block_device&&)
89 = delete;
90
95 virtual ~block_device () override;
96
101 // ----------------------------------------------------------------------
107 public:
108 virtual int
109 vioctl (int request, std::va_list args) override;
110
111 virtual ssize_t
112 read_block (void* buf, blknum_t blknum, std::size_t nblocks = 1);
113
114 virtual ssize_t
115 write_block (const void* buf, blknum_t blknum, std::size_t nblocks = 1);
116
117 // ----------------------------------------------------------------------
118
124 blocks (void);
125
130 std::size_t
132
133 std::size_t
135
136 // ----------------------------------------------------------------------
137 // Support functions.
138
140 impl (void) const;
141
146 // ----------------------------------------------------------------------
147 };
148#pragma GCC diagnostic pop
149
150 // ========================================================================
151
152#pragma GCC diagnostic push
153#if defined(__clang__)
154#pragma clang diagnostic ignored "-Wpadded"
155#elif defined(__GNUC__)
156#pragma GCC diagnostic ignored "-Wpadded"
157#endif
158
160 {
161 // ----------------------------------------------------------------------
162
163 friend class block_device;
164
165 public:
167
168 // ----------------------------------------------------------------------
169
175 public:
176 block_device_impl (void);
177
182 // The rule of five.
183 block_device_impl (const block_device_impl&) = delete;
186 operator= (const block_device_impl&)
187 = delete;
189 operator= (block_device_impl&&)
190 = delete;
191
196 virtual ~block_device_impl () override;
197
202 // ----------------------------------------------------------------------
208 public:
209 virtual ssize_t
210 do_read (void* buf, std::size_t nbyte) override;
211
212 virtual ssize_t
213 do_write (const void* buf, std::size_t nbyte) override;
214
215 virtual off_t
216 do_lseek (off_t offset, int whence) override;
217
218 virtual ssize_t
219 do_read_block (void* buf, blknum_t blknum, std::size_t nblocks)
220 = 0;
221
222 virtual ssize_t
223 do_write_block (const void* buf, blknum_t blknum, std::size_t nblocks)
224 = 0;
225
230 // ----------------------------------------------------------------------
231 protected:
236 std::size_t block_logical_size_bytes_ = 0;
237
238 std::size_t block_physical_size_bytes_ = 0;
239
240 blknum_t num_blocks_ = 0;
241
245 };
246
247#pragma GCC diagnostic pop
248
249 // ========================================================================
250
251#pragma GCC diagnostic push
252#if defined(__clang__)
253#elif defined(__GNUC__)
254#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
255#pragma GCC diagnostic ignored "-Wsuggest-final-types"
256#endif
257 template <typename T>
259 {
260 // ----------------------------------------------------------------------
261
262 public:
263 using value_type = T;
264
265 // ----------------------------------------------------------------------
266
272 public:
273 template <typename... Args>
274 block_device_implementable (const char* name, Args&&... args);
275
280 // The rule of five.
284 operator= (const block_device_implementable&)
285 = delete;
287 operator= (block_device_implementable&&)
288 = delete;
289
294 virtual ~block_device_implementable () override;
295
300 // ----------------------------------------------------------------------
306 public:
307 // Support functions.
308
310 impl (void) const;
311
316 // ----------------------------------------------------------------------
317 protected:
322 // Include the implementation as a member.
323 value_type impl_instance_;
324
328 };
329#pragma GCC diagnostic pop
330
331 // ========================================================================
332
333 template <typename T, typename L>
335 {
336 // ----------------------------------------------------------------------
337
338 public:
339 using value_type = T;
340 using lockable_type = L;
341
342 // ----------------------------------------------------------------------
343
349 public:
350 template <typename... Args>
351 block_device_lockable (const char* name, lockable_type& locker,
352 Args&&... args);
353
358 // The rule of five.
362 operator= (const block_device_lockable&)
363 = delete;
365 operator= (block_device_lockable&&)
366 = delete;
367
372 virtual ~block_device_lockable () override;
373
378 // ----------------------------------------------------------------------
384 public:
385 virtual int
386 close (void) override;
387
388 virtual ssize_t
389 read (void* buf, std::size_t nbyte) override;
390
391 virtual ssize_t
392 write (const void* buf, std::size_t nbyte) override;
393
394 virtual ssize_t
395 writev (const /* struct */ iovec* iov, int iovcnt) override;
396
397 virtual int
398 vfcntl (int cmd, std::va_list args) override;
399
400 virtual int
401 vioctl (int request, std::va_list args) override;
402
403 virtual off_t
404 lseek (off_t offset, int whence) override;
405
406 virtual ssize_t
407 read_block (void* buf, blknum_t blknum,
408 std::size_t nblocks = 1) override;
409
410 virtual ssize_t
411 write_block (const void* buf, blknum_t blknum,
412 std::size_t nblocks = 1) override;
413
414 virtual void
415 sync (void) override;
416
417 // ----------------------------------------------------------------------
418 // Support functions.
419
421 impl (void) const;
422
427 // ----------------------------------------------------------------------
428 protected:
433 value_type impl_instance_;
434
435 lockable_type& locker_;
436
440 };
441
442 // ========================================================================
443 } /* namespace posix */
444} /* namespace os */
445
446// ===== Inline & template implementations ====================================
447
448namespace os
449{
450 namespace posix
451 {
452 // ========================================================================
453
456 {
457 return impl ().num_blocks_;
458 }
459
460 inline std::size_t
462 {
463 return impl ().block_logical_size_bytes_;
464 }
465
466 inline std::size_t
468 {
469 return impl ().block_physical_size_bytes_;
470 }
471
472 inline block_device_impl&
474 {
475 return static_cast<block_device_impl&> (impl_);
476 }
477
478 // ========================================================================
479
480 template <typename T>
481 template <typename... Args>
483 const char* name, Args&&... args)
484 : block_device{ impl_instance_, name }, //
485 impl_instance_{ std::forward<Args> (args)... }
486 {
487#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
488 trace::printf ("block_device_implementable::%s(\"%s\")=@%p\n", __func__,
489 name_, this);
490#endif
491 }
492
493#pragma GCC diagnostic push
494#if defined(__clang__)
495#elif defined(__GNUC__)
496#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
497#endif
498 template <typename T>
500 {
501#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
502 trace::printf ("block_device_implementable::%s() @%p %s\n", __func__,
503 this, name_);
504#endif
505 }
506#pragma GCC diagnostic pop
507
508 template <typename T>
511 {
512 return static_cast<value_type&> (impl_);
513 }
514
515 // ========================================================================
516
517 template <typename T, typename L>
518 template <typename... Args>
520 lockable_type& locker,
521 Args&&... args)
522 : block_device{ impl_instance_, name }, //
523 impl_instance_{ std::forward<Args> (args)... }, //
524 locker_ (locker)
525 {
526#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
527 trace::printf ("block_device_lockable::%s(\"%s\")=@%p\n", __func__,
528 name_, this);
529#endif
530 }
531
532 template <typename T, typename L>
534 {
535#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
536 trace::printf ("block_device_lockable::%s() @%p %s\n", __func__, this,
537 name_);
538#endif
539 }
540
541 // ------------------------------------------------------------------------
542
543 template <typename T, typename L>
544 int
546 {
547#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
548 trace::printf ("block_device_lockable::%s() @%p\n", __func__, this);
549#endif
550
551 std::lock_guard<L> lock{ locker_ };
552
553 return block_device::close ();
554 }
555
556 template <typename T, typename L>
557 ssize_t
558 block_device_lockable<T, L>::read (void* buf, std::size_t nbyte)
559 {
560#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
561 trace::printf ("block_device_lockable::%s(0x0%X, %u) @%p\n", __func__,
562 buf, nbyte, this);
563#endif
564
565 std::lock_guard<L> lock{ locker_ };
566
567 return block_device::read (buf, nbyte);
568 }
569
570 template <typename T, typename L>
571 ssize_t
572 block_device_lockable<T, L>::write (const void* buf, std::size_t nbyte)
573 {
574#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
575 trace::printf ("block_device_lockable::%s(0x0%X, %u) @%p\n", __func__,
576 buf, nbyte, this);
577#endif
578
579 std::lock_guard<L> lock{ locker_ };
580
581 return block_device::write (buf, nbyte);
582 }
583
584 template <typename T, typename L>
585 ssize_t
587 int iovcnt)
588 {
589#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
590 trace::printf ("block_device_lockable::%s(0x0%X, %d) @%p\n", __func__,
591 iov, iovcnt, this);
592#endif
593
594 std::lock_guard<L> lock{ locker_ };
595
596 return block_device::writev (iov, iovcnt);
597 }
598
599 template <typename T, typename L>
600 int
601 block_device_lockable<T, L>::vfcntl (int cmd, std::va_list args)
602 {
603#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
604 trace::printf ("block_device_lockable::%s(%d) @%p\n", __func__, cmd,
605 this);
606#endif
607
608 std::lock_guard<L> lock{ locker_ };
609
610 return block_device::vfcntl (cmd, args);
611 }
612
613 template <typename T, typename L>
614 int
615 block_device_lockable<T, L>::vioctl (int request, std::va_list args)
616 {
617#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
618 trace::printf ("block_device_lockable::%s(%d) @%p\n", __func__, request,
619 this);
620#endif
621
622 std::lock_guard<L> lock{ locker_ };
623
624 return block_device::vioctl (request, args);
625 }
626
627 template <typename T, typename L>
628 off_t
629 block_device_lockable<T, L>::lseek (off_t offset, int whence)
630 {
631#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
632 trace::printf ("block_device_lockable::%s(%d, %d) @%p\n", __func__,
633 offset, whence, this);
634#endif
635
636 std::lock_guard<L> lock{ locker_ };
637
638 return block_device::lseek (offset, whence);
639 }
640
641 template <typename T, typename L>
642 ssize_t
644 std::size_t nblocks)
645 {
646#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
647 trace::printf ("block_device_lockable::%s(%p, %u, %u) @%p\n", __func__,
648 buf, blknum, nblocks, this);
649#endif
650
651 std::lock_guard<L> lock{ locker_ };
652
653 return block_device::read_block (buf, blknum, nblocks);
654 }
655
656 template <typename T, typename L>
657 ssize_t
659 std::size_t nblocks)
660 {
661#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
662 trace::printf ("block_device_lockable::%s(%p, %u, %u) @%p\n", __func__,
663 buf, blknum, nblocks, this);
664#endif
665
666 std::lock_guard<L> lock{ locker_ };
667
668 return block_device::write_block (buf, blknum, nblocks);
669 }
670
671 template <typename T, typename L>
672 void
674 {
675#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
676 trace::printf ("block_device_lockable::%s() @%p\n", __func__, this);
677#endif
678
679 std::lock_guard<L> lock{ locker_ };
680
681 return block_device::sync ();
682 }
683
684 template <typename T, typename L>
687 {
688 return static_cast<value_type&> (impl_);
689 }
690
691 // ========================================================================
692 } /* namespace posix */
693} /* namespace os */
694
695#pragma GCC diagnostic pop
696
697// ----------------------------------------------------------------------------
698
699#endif /* __cplusplus */
700
701// ----------------------------------------------------------------------------
702
703#endif /* CMSIS_PLUS_POSIX_IO_BLOCK_DEVICE_H_ */
virtual ssize_t do_read(void *buf, std::size_t nbyte) override
virtual off_t do_lseek(off_t offset, int whence) override
virtual ssize_t do_read_block(void *buf, blknum_t blknum, std::size_t nblocks)=0
virtual ~block_device_impl() override
virtual ssize_t do_write(const void *buf, std::size_t nbyte) override
virtual ssize_t do_write_block(const void *buf, blknum_t blknum, std::size_t nblocks)=0
block_device::blknum_t blknum_t
block_device_implementable(const char *name, Args &&... args)
virtual ~block_device_implementable() override
virtual ssize_t writev(const iovec *iov, int iovcnt) override
virtual int vfcntl(int cmd, std::va_list args) override
virtual ssize_t read(void *buf, std::size_t nbyte) override
virtual void sync(void) override
virtual off_t lseek(off_t offset, int whence) override
virtual int vioctl(int request, std::va_list args) override
virtual int close(void) override
virtual ssize_t write_block(const void *buf, blknum_t blknum, std::size_t nblocks=1) override
block_device_lockable(const char *name, lockable_type &locker, Args &&... args)
virtual ssize_t read_block(void *buf, blknum_t blknum, std::size_t nblocks=1) override
virtual ssize_t write(const void *buf, std::size_t nbyte) override
value_type & impl(void) const
virtual ~block_device_lockable() override
Block device class.
std::size_t block_physical_size_bytes(void)
virtual ~block_device() override
std::size_t block_logical_size_bytes(void)
block_device_impl & impl(void) const
virtual int vioctl(int request, std::va_list args) override
virtual ssize_t read_block(void *buf, blknum_t blknum, std::size_t nblocks=1)
virtual ssize_t write_block(const void *buf, blknum_t blknum, std::size_t nblocks=1)
Base device class.
Definition device.h:67
virtual int close(void) override
Definition device.cpp:111
virtual void sync(void)
Definition device.cpp:171
const char * name(void) const
Definition device.h:304
off_t offset(void)
Definition io.h:472
virtual ssize_t writev(const iovec *iov, int iovcnt)
Definition io.cpp:321
virtual off_t lseek(off_t offset, int whence)
Definition io.cpp:447
virtual ssize_t write(const void *buf, std::size_t nbyte)
Definition io.cpp:268
virtual ssize_t read(void *buf, std::size_t nbyte)
Definition io.cpp:217
virtual int vfcntl(int cmd, std::va_list args)
Definition io.cpp:380
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
System namespace.
Standard std namespace.
Definition uio.h:40