Demo apps refactoring
[lwext4.git] / demos / stm32f429_disco / usb_msc_lwext4.c
1 /*\r
2  * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * - Redistributions of source code must retain the above copyright\r
10  *   notice, this list of conditions and the following disclaimer.\r
11  * - Redistributions in binary form must reproduce the above copyright\r
12  *   notice, this list of conditions and the following disclaimer in the\r
13  *   documentation and/or other materials provided with the distribution.\r
14  * - The name of the author may not be used to endorse or promote products\r
15  *   derived from this software without specific prior written permission.\r
16  *\r
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  */\r
28 \r
29 #include <ext4_config.h>\r
30 #include <ext4_blockdev.h>\r
31 #include <ext4_errno.h>\r
32 #include <stdio.h>\r
33 #include <stdbool.h>\r
34 #include <string.h>\r
35 #include <fcntl.h>\r
36 \r
37 \r
38 #include <hw_init.h>\r
39 #include <usbh_core.h>\r
40 #include <usbh_msc.h>\r
41 \r
42 #include <usb_msc_lwext4.h>\r
43 #include "../../blockdev/test_lwext4.h"\r
44 \r
45 extern USBH_HandleTypeDef hUSB_Host;\r
46 \r
47 /**@brief   Block size.*/\r
48 #define USB_MSC_BLOCK_SIZE          512\r
49 \r
50 /**@brief   MBR_block ID*/\r
51 #define MBR_BLOCK_ID                0\r
52 #define MBR_PART_TABLE_OFF          446\r
53 \r
54 struct part_tab_entry {\r
55     uint8_t  status;\r
56     uint8_t  chs1[3];\r
57     uint8_t  type;\r
58     uint8_t  chs2[3];\r
59     uint32_t first_lba;\r
60     uint32_t sectors;\r
61 }__attribute__((packed));\r
62 \r
63 /**@brief   Partition block offset*/\r
64 static uint32_t part_offset;\r
65 \r
66 /**@brief IO timings*/\r
67 struct usb_msc_io_timings {\r
68     uint64_t acc_bread;\r
69     uint64_t acc_bwrite;\r
70 \r
71     uint32_t cnt_bread;\r
72     uint32_t cnt_bwrite;\r
73 \r
74     uint32_t av_bread;\r
75     uint32_t av_bwrite;\r
76 };\r
77 \r
78 \r
79 static struct usb_msc_io_timings io_timings;\r
80 \r
81 \r
82 void io_timings_clear(void)\r
83 {\r
84     memset(&io_timings, 0, sizeof(struct usb_msc_io_timings));\r
85 }\r
86 \r
87 const struct ext4_io_stats * io_timings_get(uint32_t time_sum_ms)\r
88 {\r
89     static struct ext4_io_stats s;\r
90 \r
91     s.io_read = (((float)io_timings.acc_bread * 100.0) / time_sum_ms);\r
92     s.io_read /= 1000.0;\r
93 \r
94     s.io_write= (((float)io_timings.acc_bwrite * 100.0) / time_sum_ms);\r
95     s.io_write /= 1000.0;\r
96 \r
97     s.cpu = 100.0 - s.io_read - s.io_write;\r
98 \r
99     return &s;\r
100 }\r
101 \r
102 \r
103 /**********************BLOCKDEV INTERFACE**************************************/\r
104 static int usb_msc_open(struct ext4_blockdev *bdev);\r
105 static int usb_msc_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
106     uint32_t blk_cnt);\r
107 static int usb_msc_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
108     uint64_t blk_id, uint32_t blk_cnt);\r
109 static int usb_msc_close(struct  ext4_blockdev *bdev);\r
110 \r
111 \r
112 /******************************************************************************/\r
113 EXT4_BLOCKDEV_STATIC_INSTANCE(\r
114     _usb_msc,\r
115     USB_MSC_BLOCK_SIZE,\r
116     0,\r
117     usb_msc_open,\r
118     usb_msc_bread,\r
119     usb_msc_bwrite,\r
120     usb_msc_close\r
121 );\r
122 \r
123 /******************************************************************************/\r
124 EXT4_BCACHE_STATIC_INSTANCE(_usb_msc_cache, CONFIG_BLOCK_DEV_CACHE_SIZE, EXT_LOGICAL_BLOCK_SIZE);\r
125 \r
126 /******************************************************************************/\r
127 \r
128 static int usb_msc_open(struct ext4_blockdev *bdev)\r
129 {\r
130     (void)bdev;\r
131 \r
132     static uint8_t mbr[512];\r
133     struct part_tab_entry *part0;\r
134     uint8_t status;\r
135 \r
136     if(!hw_usb_connected())\r
137         return EIO;\r
138 \r
139     status = USBH_MSC_Read(&hUSB_Host, 0, 0, mbr, 1);\r
140     if(status != USBH_OK)\r
141         return EIO;\r
142 \r
143     part0 = (struct part_tab_entry *)(mbr + MBR_PART_TABLE_OFF);\r
144 \r
145     MSC_LUNTypeDef lun;\r
146     USBH_MSC_GetLUNInfo(&hUSB_Host, 0, &lun);\r
147 \r
148     part_offset = part0->first_lba;\r
149     _usb_msc.ph_bcnt = lun.capacity.block_nbr;\r
150 \r
151     return hw_usb_connected() ? EOK : EIO;\r
152 }\r
153 \r
154 static int usb_msc_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
155     uint32_t blk_cnt)\r
156 {\r
157     uint8_t status;\r
158 \r
159     uint64_t v = tim_get_us();\r
160 \r
161     if(!hw_usb_connected())\r
162         return EIO;\r
163 \r
164     while(!USBH_MSC_UnitIsReady(&hUSB_Host, 0))\r
165         ;\r
166 \r
167     status = USBH_MSC_Read(&hUSB_Host, 0, blk_id + part_offset, buf, blk_cnt);\r
168     if(status != USBH_OK)\r
169         return EIO;\r
170 \r
171     io_timings.acc_bread += tim_get_us() - v;\r
172     io_timings.cnt_bread++;\r
173     io_timings.av_bread = io_timings.acc_bread / io_timings.cnt_bread;\r
174 \r
175     return EOK;\r
176 \r
177 }\r
178 \r
179 static int usb_msc_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
180     uint64_t blk_id, uint32_t blk_cnt)\r
181 {\r
182     uint8_t status;\r
183 \r
184     uint64_t v = tim_get_us();\r
185 \r
186     if(!hw_usb_connected())\r
187         return EIO;\r
188 \r
189     while(!USBH_MSC_UnitIsReady(&hUSB_Host, 0))\r
190         ;\r
191 \r
192     status = USBH_MSC_Write(&hUSB_Host, 0, blk_id + part_offset, (void *)buf, blk_cnt);\r
193     if(status != USBH_OK)\r
194         return EIO;\r
195 \r
196     io_timings.acc_bwrite += tim_get_us() - v;\r
197     io_timings.cnt_bwrite++;\r
198     io_timings.av_bwrite = io_timings.acc_bwrite / io_timings.cnt_bwrite;\r
199 \r
200     return EOK;\r
201 }\r
202 \r
203 static int usb_msc_close(struct  ext4_blockdev *bdev)\r
204 {\r
205     (void)bdev;\r
206     return EOK;\r
207 }\r
208 \r
209 /******************************************************************************/\r
210 \r
211 struct ext4_bcache*   ext4_usb_msc_cache_get(void)\r
212 {\r
213     return &_usb_msc_cache;\r
214 }\r
215 \r
216 \r
217 struct ext4_blockdev* ext4_usb_msc_get(void)\r
218 {\r
219     return &_usb_msc;\r
220 }\r
221 \r