Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
4 : : * Original template for this file comes from:
5 : : * Low level disk I/O module skeleton for FatFs, (C)ChaN, 2013
6 : : *
7 : : * The MIT License (MIT)
8 : : *
9 : : * Copyright (c) 2013, 2014 Damien P. George
10 : : *
11 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
12 : : * of this software and associated documentation files (the "Software"), to deal
13 : : * in the Software without restriction, including without limitation the rights
14 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 : : * copies of the Software, and to permit persons to whom the Software is
16 : : * furnished to do so, subject to the following conditions:
17 : : *
18 : : * The above copyright notice and this permission notice shall be included in
19 : : * all copies or substantial portions of the Software.
20 : : *
21 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 : : * THE SOFTWARE.
28 : : */
29 : :
30 : : #include "py/mpconfig.h"
31 : : #if MICROPY_VFS && MICROPY_VFS_FAT
32 : :
33 : : #include <stdint.h>
34 : : #include <stdio.h>
35 : :
36 : : #include "py/mphal.h"
37 : :
38 : : #include "py/runtime.h"
39 : : #include "py/binary.h"
40 : : #include "py/objarray.h"
41 : : #include "py/mperrno.h"
42 : : #include "lib/oofatfs/ff.h"
43 : : #include "lib/oofatfs/diskio.h"
44 : : #include "extmod/vfs_fat.h"
45 : :
46 : : typedef void *bdev_t;
47 : 2824 : static fs_user_mount_t *disk_get_device(void *bdev) {
48 : 2824 : return (fs_user_mount_t *)bdev;
49 : : }
50 : :
51 : : /*-----------------------------------------------------------------------*/
52 : : /* Read Sector(s) */
53 : : /*-----------------------------------------------------------------------*/
54 : :
55 : 488 : DRESULT disk_read(
56 : : bdev_t pdrv, /* Physical drive nmuber (0..) */
57 : : BYTE *buff, /* Data buffer to store read data */
58 : : DWORD sector, /* Sector address (LBA) */
59 : : UINT count /* Number of sectors to read (1..128) */
60 : : ) {
61 : 488 : fs_user_mount_t *vfs = disk_get_device(pdrv);
62 [ + - ]: 488 : if (vfs == NULL) {
63 : : return RES_PARERR;
64 : : }
65 : :
66 : 488 : int ret = mp_vfs_blockdev_read(&vfs->blockdev, sector, count, buff);
67 : :
68 : 488 : return ret == 0 ? RES_OK : RES_ERROR;
69 : : }
70 : :
71 : : /*-----------------------------------------------------------------------*/
72 : : /* Write Sector(s) */
73 : : /*-----------------------------------------------------------------------*/
74 : :
75 : 854 : DRESULT disk_write(
76 : : bdev_t pdrv, /* Physical drive nmuber (0..) */
77 : : const BYTE *buff, /* Data to be written */
78 : : DWORD sector, /* Sector address (LBA) */
79 : : UINT count /* Number of sectors to write (1..128) */
80 : : ) {
81 : 854 : fs_user_mount_t *vfs = disk_get_device(pdrv);
82 [ + - ]: 854 : if (vfs == NULL) {
83 : : return RES_PARERR;
84 : : }
85 : :
86 : 854 : int ret = mp_vfs_blockdev_write(&vfs->blockdev, sector, count, buff);
87 : :
88 [ + - ]: 854 : if (ret == -MP_EROFS) {
89 : : // read-only block device
90 : : return RES_WRPRT;
91 : : }
92 : :
93 : 854 : return ret == 0 ? RES_OK : RES_ERROR;
94 : : }
95 : :
96 : :
97 : : /*-----------------------------------------------------------------------*/
98 : : /* Miscellaneous Functions */
99 : : /*-----------------------------------------------------------------------*/
100 : :
101 : 1482 : DRESULT disk_ioctl(
102 : : bdev_t pdrv, /* Physical drive nmuber (0..) */
103 : : BYTE cmd, /* Control code */
104 : : void *buff /* Buffer to send/receive control data */
105 : : ) {
106 : 1482 : fs_user_mount_t *vfs = disk_get_device(pdrv);
107 [ + - ]: 1482 : if (vfs == NULL) {
108 : : return RES_PARERR;
109 : : }
110 : :
111 : : // First part: call the relevant method of the underlying block device
112 : 1482 : static const uint8_t op_map[8] = {
113 : : [CTRL_SYNC] = MP_BLOCKDEV_IOCTL_SYNC,
114 : : [GET_SECTOR_COUNT] = MP_BLOCKDEV_IOCTL_BLOCK_COUNT,
115 : : [GET_SECTOR_SIZE] = MP_BLOCKDEV_IOCTL_BLOCK_SIZE,
116 : : [IOCTL_INIT] = MP_BLOCKDEV_IOCTL_INIT,
117 : : };
118 : 1482 : uint8_t bp_op = op_map[cmd & 7];
119 : 1482 : mp_obj_t ret = mp_const_none;
120 [ + + ]: 1482 : if (bp_op != 0) {
121 : 358 : ret = mp_vfs_blockdev_ioctl(&vfs->blockdev, bp_op, 0);
122 : : }
123 : :
124 : : // Second part: convert the result for return
125 [ + + + + : 1482 : switch (cmd) {
- + ]
126 : : case CTRL_SYNC:
127 : : return RES_OK;
128 : :
129 : 26 : case GET_SECTOR_COUNT: {
130 : 26 : *((DWORD *)buff) = mp_obj_get_int(ret);
131 : 26 : return RES_OK;
132 : : }
133 : :
134 : 80 : case GET_SECTOR_SIZE: {
135 [ + + ]: 80 : if (ret == mp_const_none) {
136 : : // Default sector size
137 : 6 : *((WORD *)buff) = 512;
138 : : } else {
139 : 74 : *((WORD *)buff) = mp_obj_get_int(ret);
140 : : }
141 : : // need to store ssize because we use it in disk_read/disk_write
142 : 80 : vfs->blockdev.block_size = *((WORD *)buff);
143 : 80 : return RES_OK;
144 : : }
145 : :
146 : 26 : case GET_BLOCK_SIZE:
147 : 26 : *((DWORD *)buff) = 1; // erase block size in units of sector size
148 : 26 : return RES_OK;
149 : :
150 : 1178 : case IOCTL_INIT:
151 : : case IOCTL_STATUS: {
152 : 1178 : DSTATUS stat;
153 [ - + - - ]: 1178 : if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
154 : : // error initialising
155 : : stat = STA_NOINIT;
156 [ + - ]: 1178 : } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) {
157 : : stat = STA_PROTECT;
158 : : } else {
159 : 1178 : stat = 0;
160 : : }
161 : 1178 : *((DSTATUS *)buff) = stat;
162 : 1178 : return RES_OK;
163 : : }
164 : :
165 : 0 : default:
166 : 0 : return RES_PARERR;
167 : : }
168 : : }
169 : :
170 : : #endif // MICROPY_VFS && MICROPY_VFS_FAT
|