µ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++ distribution.
3 * (https://github.com/micro-os-plus)
4 * Copyright (c) 2015-2023 Liviu Ionescu. All rights reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software
7 * for any purpose is hereby granted, under the terms of the MIT license.
8 *
9 * If a copy of the license was not distributed with this file, it can
10 * be obtained from https://opensource.org/licenses/mit/.
11 */
12
13#ifndef CMSIS_PLUS_POSIX_IO_BLOCK_DEVICE_H_
14#define CMSIS_PLUS_POSIX_IO_BLOCK_DEVICE_H_
15
16// ----------------------------------------------------------------------------
17
18#if defined(__cplusplus)
19
20// ----------------------------------------------------------------------------
21
22#if defined(OS_USE_OS_APP_CONFIG_H)
23#include <cmsis-plus/os-app-config.h>
24#endif
25
27
28// ----------------------------------------------------------------------------
29
30#pragma GCC diagnostic push
31#if defined(__clang__)
32#pragma clang diagnostic ignored "-Wc++98-compat"
33#endif
34
35// ----------------------------------------------------------------------------
36
37namespace os
38{
39 namespace posix
40 {
41 // ------------------------------------------------------------------------
42
43 class block_device_impl;
44
45 // ========================================================================
46
47 // TODO: add support to indicate that there is no media in drive.
48 // TODO: add support to indicate the media is write protected.
49
55#pragma GCC diagnostic push
56#if defined(__clang__)
57#elif defined(__GNUC__)
58#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
59#pragma GCC diagnostic ignored "-Wsuggest-final-types"
60#endif
61 class block_device : public device
62 {
63 // ----------------------------------------------------------------------
64
65 public:
66
67 using blknum_t = std::size_t;
68
69 // ----------------------------------------------------------------------
70
76 public:
77
79
84 // The rule of five.
85 block_device (const block_device&) = delete;
86 block_device (block_device&&) = delete;
88 operator= (const block_device&) = delete;
90 operator= (block_device&&) = delete;
91
96 virtual
97 ~block_device () override;
98
103 // ----------------------------------------------------------------------
109 public:
110
111 virtual int
112 vioctl (int request, std::va_list args) override;
113
114 virtual ssize_t
115 read_block (void* buf, blknum_t blknum, std::size_t nblocks = 1);
116
117 virtual ssize_t
118 write_block (const void* buf, blknum_t blknum, std::size_t nblocks = 1);
119
120 // ----------------------------------------------------------------------
121
127 blocks (void);
128
133 std::size_t
135
136 std::size_t
138
139 // ----------------------------------------------------------------------
140 // Support functions.
141
143 impl (void) const;
144
149 // ----------------------------------------------------------------------
150 };
151#pragma GCC diagnostic pop
152
153 // ========================================================================
154
155#pragma GCC diagnostic push
156#if defined(__clang__)
157#pragma clang diagnostic ignored "-Wpadded"
158#elif defined(__GNUC__)
159#pragma GCC diagnostic ignored "-Wpadded"
160#endif
161
163 {
164 // ----------------------------------------------------------------------
165
166 friend class block_device;
167
168 public:
169
171
172 // ----------------------------------------------------------------------
173
179 public:
180
181 block_device_impl (void);
182
187 // The rule of five.
188 block_device_impl (const block_device_impl&) = delete;
191 operator= (const block_device_impl&) = delete;
193 operator= (block_device_impl&&) = delete;
194
199 virtual
200 ~block_device_impl () override;
201
206 // ----------------------------------------------------------------------
212 public:
213
214 virtual ssize_t
215 do_read (void* buf, std::size_t nbyte) override;
216
217 virtual ssize_t
218 do_write (const void* buf, std::size_t nbyte) override;
219
220 virtual off_t
221 do_lseek (off_t offset, int whence) override;
222
223 virtual ssize_t
224 do_read_block (void* buf, blknum_t blknum, std::size_t nblocks) = 0;
225
226 virtual ssize_t
227 do_write_block (const void* buf, blknum_t blknum,
228 std::size_t nblocks) = 0;
229
234 // ----------------------------------------------------------------------
235 protected:
236
241 std::size_t block_logical_size_bytes_ = 0;
242
243 std::size_t block_physical_size_bytes_ = 0;
244
245 blknum_t num_blocks_ = 0;
246
250 };
251
252#pragma GCC diagnostic pop
253
254 // ========================================================================
255
256#pragma GCC diagnostic push
257#if defined(__clang__)
258#elif defined(__GNUC__)
259#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
260#pragma GCC diagnostic ignored "-Wsuggest-final-types"
261#endif
262 template<typename T>
264 {
265 // --------------------------------------------------------------------
266
267 public:
268
269 using value_type = T;
270
271 // --------------------------------------------------------------------
272
278 public:
279
280 template<typename ... Args>
281 block_device_implementable (const char* name, Args&&... args);
282
287 // The rule of five.
291 operator= (const block_device_implementable&) = delete;
293 operator= (block_device_implementable&&) = delete;
294
299 virtual
300 ~block_device_implementable () override;
301
306 // --------------------------------------------------------------------
312 public:
313
314 // Support functions.
315
317 impl (void) const;
318
323 // --------------------------------------------------------------------
324 protected:
325
330 // Include the implementation as a member.
331 value_type impl_instance_;
332
336 };
337#pragma GCC diagnostic pop
338
339 // ========================================================================
340
341 template<typename T, typename L>
343 {
344 // --------------------------------------------------------------------
345
346 public:
347
348 using value_type = T;
349 using lockable_type = L;
350
351 // --------------------------------------------------------------------
352
358 public:
359
360 template<typename ... Args>
361 block_device_lockable (const char* name, lockable_type& locker,
362 Args&&... args);
363
368 // The rule of five.
372 operator= (const block_device_lockable&) = delete;
374 operator= (block_device_lockable&&) = delete;
375
380 virtual
381 ~block_device_lockable () override;
382
387 // --------------------------------------------------------------------
393 public:
394
395 virtual int
396 close (void) override;
397
398 virtual ssize_t
399 read (void* buf, std::size_t nbyte) override;
400
401 virtual ssize_t
402 write (const void* buf, std::size_t nbyte) override;
403
404 virtual ssize_t
405 writev (const /* struct */ iovec* iov, int iovcnt) override;
406
407 virtual int
408 vfcntl (int cmd, std::va_list args) override;
409
410 virtual int
411 vioctl (int request, std::va_list args) override;
412
413 virtual off_t
414 lseek (off_t offset, int whence) override;
415
416 virtual ssize_t
417 read_block (void* buf, blknum_t blknum, std::size_t nblocks = 1)
418 override;
419
420 virtual ssize_t
421 write_block (const void* buf, blknum_t blknum, std::size_t nblocks = 1)
422 override;
423
424 virtual void
425 sync (void) override;
426
427 // --------------------------------------------------------------------
428 // Support functions.
429
431 impl (void) const;
432
437 // --------------------------------------------------------------------
438 protected:
439
444 value_type impl_instance_;
445
446 lockable_type& locker_;
447
451 };
452
453 // ==========================================================================
454 } /* namespace posix */
455} /* namespace os */
456
457// ===== Inline & template implementations ====================================
458
459namespace os
460{
461 namespace posix
462 {
463 // ========================================================================
464
467 {
468 return impl ().num_blocks_;
469 }
470
471 inline std::size_t
473 {
474 return impl ().block_logical_size_bytes_;
475 }
476
477 inline std::size_t
479 {
480 return impl ().block_physical_size_bytes_;
481 }
482
483 inline block_device_impl&
485 {
486 return static_cast<block_device_impl&> (impl_);
487 }
488
489 // ========================================================================
490
491 template<typename T>
492 template<typename ... Args>
494 const char* name, Args&&... args) :
496 { impl_instance_, name }, //
497 impl_instance_
498 { std::forward<Args>(args)... }
499 {
500#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
501 trace::printf ("block_device_implementable::%s(\"%s\")=@%p\n",
502 __func__, name_, this);
503#endif
504 }
505
506#pragma GCC diagnostic push
507#if defined(__clang__)
508#elif defined(__GNUC__)
509#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
510#endif
511 template<typename T>
513 {
514#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
515 trace::printf ("block_device_implementable::%s() @%p %s\n", __func__,
516 this, name_);
517#endif
518 }
519#pragma GCC diagnostic pop
520
521 template<typename T>
524 {
525 return static_cast<value_type&> (impl_);
526 }
527
528 // ========================================================================
529
530 template<typename T, typename L>
531 template<typename ... Args>
533 const char* name, lockable_type& locker, Args&&... args) :
535 { impl_instance_, name }, //
536 impl_instance_
537 { std::forward<Args>(args)... }, //
538 locker_ (locker)
539 {
540#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
541 trace::printf ("block_device_lockable::%s(\"%s\")=@%p\n", __func__,
542 name_, this);
543#endif
544 }
545
546 template<typename T, typename L>
548 {
549#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
550 trace::printf ("block_device_lockable::%s() @%p %s\n", __func__, this,
551 name_);
552#endif
553 }
554
555 // ------------------------------------------------------------------------
556
557 template<typename T, typename L>
558 int
560 {
561#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
562 trace::printf ("block_device_lockable::%s() @%p\n", __func__, this);
563#endif
564
565 std::lock_guard<L> lock
566 { locker_ };
567
568 return block_device::close ();
569 }
570
571 template<typename T, typename L>
572 ssize_t
573 block_device_lockable<T, L>::read (void* buf, std::size_t nbyte)
574 {
575#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
576 trace::printf ("block_device_lockable::%s(0x0%X, %u) @%p\n", __func__,
577 buf, nbyte, this);
578#endif
579
580 std::lock_guard<L> lock
581 { locker_ };
582
583 return block_device::read (buf, nbyte);
584 }
585
586 template<typename T, typename L>
587 ssize_t
588 block_device_lockable<T, L>::write (const void* buf, std::size_t nbyte)
589 {
590#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
591 trace::printf ("block_device_lockable::%s(0x0%X, %u) @%p\n", __func__,
592 buf, nbyte, this);
593#endif
594
595 std::lock_guard<L> lock
596 { locker_ };
597
598 return block_device::write (buf, nbyte);
599 }
600
601 template<typename T, typename L>
602 ssize_t
603 block_device_lockable<T, L>::writev (const /* struct */ iovec* iov, int iovcnt)
604 {
605#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
606 trace::printf ("block_device_lockable::%s(0x0%X, %d) @%p\n", __func__,
607 iov, iovcnt, this);
608#endif
609
610 std::lock_guard<L> lock
611 { locker_ };
612
613 return block_device::writev (iov, iovcnt);
614 }
615
616 template<typename T, typename L>
617 int
618 block_device_lockable<T, L>::vfcntl (int cmd, std::va_list args)
619 {
620#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
621 trace::printf ("block_device_lockable::%s(%d) @%p\n", __func__, cmd,
622 this);
623#endif
624
625 std::lock_guard<L> lock
626 { locker_ };
627
628 return block_device::vfcntl (cmd, args);
629 }
630
631 template<typename T, typename L>
632 int
633 block_device_lockable<T, L>::vioctl (int request, std::va_list args)
634 {
635#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
636 trace::printf ("block_device_lockable::%s(%d) @%p\n", __func__, request,
637 this);
638#endif
639
640 std::lock_guard<L> lock
641 { locker_ };
642
643 return block_device::vioctl (request, args);
644 }
645
646 template<typename T, typename L>
647 off_t
648 block_device_lockable<T, L>::lseek (off_t offset, int whence)
649 {
650#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
651 trace::printf ("block_device_lockable::%s(%d, %d) @%p\n", __func__,
652 offset, whence, this);
653#endif
654
655 std::lock_guard<L> lock
656 { locker_ };
657
658 return block_device::lseek (offset, whence);
659 }
660
661 template<typename T, typename L>
662 ssize_t
664 std::size_t nblocks)
665 {
666#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
667 trace::printf ("block_device_lockable::%s(%p, %u, %u) @%p\n", __func__,
668 buf, blknum, nblocks, this);
669#endif
670
671 std::lock_guard<L> lock
672 { locker_ };
673
674 return block_device::read_block (buf, blknum, nblocks);
675 }
676
677 template<typename T, typename L>
678 ssize_t
680 blknum_t blknum,
681 std::size_t nblocks)
682 {
683#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
684 trace::printf ("block_device_lockable::%s(%p, %u, %u) @%p\n", __func__,
685 buf, blknum, nblocks, this);
686#endif
687
688 std::lock_guard<L> lock
689 { locker_ };
690
691 return block_device::write_block (buf, blknum, nblocks);
692 }
693
694 template<typename T, typename L>
695 void
697 {
698#if defined(OS_TRACE_POSIX_IO_BLOCK_DEVICE)
699 trace::printf ("block_device_lockable::%s() @%p\n", __func__, this);
700#endif
701
702 std::lock_guard<L> lock
703 { locker_ };
704
705 return block_device::sync ();
706 }
707
708 template<typename T, typename L>
711 {
712 return static_cast<value_type&> (impl_);
713 }
714
715 // ==========================================================================
716 } /* namespace posix */
717} /* namespace os */
718
719#pragma GCC diagnostic pop
720
721// ----------------------------------------------------------------------------
722
723#endif /* __cplusplus */
724
725// ----------------------------------------------------------------------------
726
727#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:68
virtual int close(void) override
Definition device.cpp:114
virtual void sync(void)
Definition device.cpp:174
const char * name(void) const
Definition device.h:307
off_t offset(void)
Definition io.h:476
virtual ssize_t writev(const iovec *iov, int iovcnt)
Definition io.cpp:322
virtual off_t lseek(off_t offset, int whence)
Definition io.cpp:448
virtual ssize_t write(const void *buf, std::size_t nbyte)
Definition io.cpp:269
virtual ssize_t read(void *buf, std::size_t nbyte)
Definition io.cpp:218
virtual int vfcntl(int cmd, std::va_list args)
Definition io.cpp:381
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:60
System namespace.
Definition uio.h:41