1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2011-12-12 Yi Qiu first version 9 */ 10 11 #include <rtthread.h> 12 #include <dfs_fs.h> 13 #include <drivers/usb_host.h> 14 #include "mass.h" 15 16 #ifdef RT_USBH_MSTORAGE 17 18 #define UDISK_MAX_COUNT 8 19 static rt_uint8_t _udisk_idset = 0; 20 21 static int udisk_get_id(void) 22 { 23 int i; 24 25 for(i=0; i< UDISK_MAX_COUNT; i++) 26 { 27 if((_udisk_idset & (1 << i)) != 0) continue; 28 else break; 29 } 30 31 /* it should not happen */ 32 if(i == UDISK_MAX_COUNT) RT_ASSERT(0); 33 34 _udisk_idset |= (1 << i); 35 return i; 36 } 37 38 static void udisk_free_id(int id) 39 { 40 RT_ASSERT(id < UDISK_MAX_COUNT) 41 42 _udisk_idset &= ~(1 << id); 43 } 44 45 /** 46 * This function will initialize the udisk device 47 * 48 * @param dev the pointer of device driver structure 49 * 50 * @return RT_EOK 51 */ 52 static rt_err_t rt_udisk_init(rt_device_t dev) 53 { 54 return RT_EOK; 55 } 56 57 /** 58 * This function will read some data from a device. 59 * 60 * @param dev the pointer of device driver structure 61 * @param pos the position of reading 62 * @param buffer the data buffer to save read data 63 * @param size the size of buffer 64 * 65 * @return the actually read size on successful, otherwise negative returned. 66 */ 67 static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer, 68 rt_size_t size) 69 { 70 rt_err_t ret; 71 struct uhintf* intf; 72 struct ustor_data* data; 73 int timeout = USB_TIMEOUT_LONG; 74 75 /* check parameter */ 76 RT_ASSERT(dev != RT_NULL); 77 RT_ASSERT(buffer != RT_NULL); 78 79 if(size > 4096) timeout *= 2; 80 81 data = (struct ustor_data*)dev->user_data; 82 intf = data->intf; 83 84 ret = rt_usbh_storage_read10(intf, (rt_uint8_t*)buffer, pos, size, timeout); 85 86 if (ret != RT_EOK) 87 { 88 rt_kprintf("usb mass_storage read failed\n"); 89 return 0; 90 } 91 92 return size; 93 } 94 95 /** 96 * This function will write some data to a device. 97 * 98 * @param dev the pointer of device driver structure 99 * @param pos the position of written 100 * @param buffer the data buffer to be written to device 101 * @param size the size of buffer 102 * 103 * @return the actually written size on successful, otherwise negative returned. 104 */ 105 static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer, 106 rt_size_t size) 107 { 108 rt_err_t ret; 109 struct uhintf* intf; 110 struct ustor_data* data; 111 int timeout = USB_TIMEOUT_LONG; 112 113 /* check parameter */ 114 RT_ASSERT(dev != RT_NULL); 115 RT_ASSERT(buffer != RT_NULL); 116 117 if(size * SECTOR_SIZE > 4096) timeout *= 2; 118 119 data = (struct ustor_data*)dev->user_data; 120 intf = data->intf; 121 122 ret = rt_usbh_storage_write10(intf, (rt_uint8_t*)buffer, pos, size, timeout); 123 if (ret != RT_EOK) 124 { 125 rt_kprintf("usb mass_storage write %d sector failed\n", size); 126 return 0; 127 } 128 129 return size; 130 } 131 132 /** 133 * This function will execute SCSI_INQUIRY_CMD command to get inquiry data. 134 * 135 * @param intf the interface instance. 136 * @param buffer the data buffer to save inquiry data 137 * 138 * @return the error code, RT_EOK on successfully. 139 */ 140 static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args) 141 { 142 ustor_t stor; 143 struct ustor_data* data; 144 145 /* check parameter */ 146 RT_ASSERT(dev != RT_NULL); 147 148 data = (struct ustor_data*)dev->user_data; 149 stor = (ustor_t)data->intf->user_data; 150 151 if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) 152 { 153 struct rt_device_blk_geometry *geometry; 154 155 geometry = (struct rt_device_blk_geometry *)args; 156 if (geometry == RT_NULL) return -RT_ERROR; 157 158 geometry->bytes_per_sector = SECTOR_SIZE; 159 geometry->block_size = stor->capicity[1]; 160 geometry->sector_count = stor->capicity[0]; 161 } 162 163 return RT_EOK; 164 } 165 166 #ifdef RT_USING_DEVICE_OPS 167 const static struct rt_device_ops udisk_device_ops = 168 { 169 rt_udisk_init, 170 RT_NULL, 171 RT_NULL, 172 rt_udisk_read, 173 rt_udisk_write, 174 rt_udisk_control 175 }; 176 #endif 177 178 /** 179 * This function will run udisk driver when usb disk is detected. 180 * 181 * @param intf the usb interface instance. 182 * 183 * @return the error code, RT_EOK on successfully. 184 */ 185 rt_err_t rt_udisk_run(struct uhintf* intf) 186 { 187 int i = 0; 188 rt_err_t ret; 189 char dname[4]; 190 char sname[8]; 191 rt_uint8_t max_lun, *sector, sense[18], inquiry[36]; 192 struct dfs_partition part[MAX_PARTITION_COUNT]; 193 ustor_t stor; 194 195 /* check parameter */ 196 RT_ASSERT(intf != RT_NULL); 197 198 /* set interface */ 199 // ret = rt_usbh_set_interface(intf->device, intf->intf_desc->bInterfaceNumber); 200 // if(ret != RT_EOK) 201 // rt_usbh_clear_feature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT); 202 /* reset mass storage class device */ 203 ret = rt_usbh_storage_reset(intf); 204 if(ret != RT_EOK) return ret; 205 206 stor = (ustor_t)intf->user_data; 207 208 /* get max logic unit number */ 209 ret = rt_usbh_storage_get_max_lun(intf, &max_lun); 210 if(ret != RT_EOK) 211 rt_usbh_clear_feature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT); 212 213 /* reset pipe in endpoint */ 214 if(stor->pipe_in->status == UPIPE_STATUS_STALL) 215 { 216 ret = rt_usbh_clear_feature(intf->device, 217 stor->pipe_in->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT); 218 if(ret != RT_EOK) return ret; 219 } 220 221 222 /* reset pipe out endpoint */ 223 if(stor->pipe_out->status == UPIPE_STATUS_STALL) 224 { 225 ret = rt_usbh_clear_feature(intf->device, 226 stor->pipe_out->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT); 227 if(ret != RT_EOK) return ret; 228 } 229 230 while((ret = rt_usbh_storage_inquiry(intf, inquiry)) != RT_EOK) 231 { 232 if(ret == -RT_EIO) return ret; 233 234 rt_thread_delay(5); 235 if(i++ < 10) continue; 236 rt_kprintf("rt_usbh_storage_inquiry error\n"); 237 return -RT_ERROR; 238 } 239 240 i = 0; 241 242 /* wait device ready */ 243 while((ret = rt_usbh_storage_test_unit_ready(intf)) != RT_EOK) 244 { 245 if(ret == -RT_EIO) return ret; 246 247 ret = rt_usbh_storage_request_sense(intf, sense); 248 if(ret == -RT_EIO) return ret; 249 250 rt_thread_delay(10); 251 if(i++ < 10) continue; 252 253 rt_kprintf("rt_usbh_storage_test_unit_ready error\n"); 254 return -RT_ERROR; 255 } 256 257 i = 0; 258 rt_memset(stor->capicity, 0, sizeof(stor->capicity)); 259 260 /* get storage capacity */ 261 while((ret = rt_usbh_storage_get_capacity(intf, 262 (rt_uint8_t*)stor->capicity)) != RT_EOK) 263 { 264 if(ret == -RT_EIO) return ret; 265 266 rt_thread_delay(50); 267 if(i++ < 10) continue; 268 269 stor->capicity[0] = 2880; 270 stor->capicity[1] = 0x200; 271 272 rt_kprintf("rt_usbh_storage_get_capacity error\n"); 273 break; 274 } 275 276 stor->capicity[0] = uswap_32(stor->capicity[0]); 277 stor->capicity[1] = uswap_32(stor->capicity[1]); 278 stor->capicity[0] += 1; 279 280 RT_DEBUG_LOG(RT_DEBUG_USB, ("capicity %d, block size %d\n", 281 stor->capicity[0], stor->capicity[1])); 282 283 /* get the first sector to read partition table */ 284 sector = (rt_uint8_t*) rt_malloc (SECTOR_SIZE); 285 if (sector == RT_NULL) 286 { 287 rt_kprintf("allocate partition sector buffer failed\n"); 288 return -RT_ERROR; 289 } 290 291 rt_memset(sector, 0, SECTOR_SIZE); 292 293 RT_DEBUG_LOG(RT_DEBUG_USB, ("read partition table\n")); 294 295 /* get the partition table */ 296 ret = rt_usbh_storage_read10(intf, sector, 0, 1, USB_TIMEOUT_LONG); 297 if(ret != RT_EOK) 298 { 299 rt_kprintf("read parition table error\n"); 300 301 rt_free(sector); 302 return -RT_ERROR; 303 } 304 305 RT_DEBUG_LOG(RT_DEBUG_USB, ("finished reading partition\n")); 306 307 for(i=0; i<MAX_PARTITION_COUNT; i++) 308 { 309 /* get the first partition */ 310 ret = dfs_filesystem_get_partition(&part[i], sector, i); 311 if (ret == RT_EOK) 312 { 313 struct ustor_data* data = rt_malloc(sizeof(struct ustor_data)); 314 rt_memset(data, 0, sizeof(struct ustor_data)); 315 data->intf = intf; 316 data->udisk_id = udisk_get_id(); 317 rt_snprintf(dname, 6, "ud%d-%d", data->udisk_id, i); 318 rt_snprintf(sname, 8, "sem_ud%d", i); 319 data->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); 320 321 /* register sdcard device */ 322 stor->dev[i].type = RT_Device_Class_Block; 323 #ifdef RT_USING_DEVICE_OPS 324 stor->dev[i].ops = &udisk_device_ops; 325 #else 326 stor->dev[i].init = rt_udisk_init; 327 stor->dev[i].read = rt_udisk_read; 328 stor->dev[i].write = rt_udisk_write; 329 stor->dev[i].control = rt_udisk_control; 330 #endif 331 stor->dev[i].user_data = (void*)data; 332 333 rt_device_register(&stor->dev[i], dname, RT_DEVICE_FLAG_RDWR | 334 RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); 335 336 stor->dev_cnt++; 337 if (dfs_mount(stor->dev[i].parent.name, UDISK_MOUNTPOINT, "elm", 338 0, 0) == 0) 339 { 340 RT_DEBUG_LOG(RT_DEBUG_USB, ("udisk part %d mount successfully\n", i)); 341 } 342 else 343 { 344 RT_DEBUG_LOG(RT_DEBUG_USB, ("udisk part %d mount failed\n", i)); 345 } 346 } 347 else 348 { 349 if(i == 0) 350 { 351 struct ustor_data* data = rt_malloc(sizeof(struct ustor_data)); 352 rt_memset(data, 0, sizeof(struct ustor_data)); 353 data->udisk_id = udisk_get_id(); 354 355 /* there is no partition table */ 356 data->part.offset = 0; 357 data->part.size = 0; 358 data->intf = intf; 359 data->part.lock = rt_sem_create("sem_ud", 1, RT_IPC_FLAG_FIFO); 360 361 rt_snprintf(dname, 7, "udisk%d", data->udisk_id); 362 363 /* register sdcard device */ 364 stor->dev[0].type = RT_Device_Class_Block; 365 #ifdef RT_USING_DEVICE_OPS 366 stor->dev[i].ops = &udisk_device_ops; 367 #else 368 stor->dev[0].init = rt_udisk_init; 369 stor->dev[0].read = rt_udisk_read; 370 stor->dev[0].write = rt_udisk_write; 371 stor->dev[0].control = rt_udisk_control; 372 #endif 373 stor->dev[0].user_data = (void*)data; 374 375 rt_device_register(&stor->dev[0], dname, 376 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE 377 | RT_DEVICE_FLAG_STANDALONE); 378 379 stor->dev_cnt++; 380 if (dfs_mount(stor->dev[0].parent.name, UDISK_MOUNTPOINT, 381 "elm", 0, 0) == 0) 382 { 383 rt_kprintf("Mount FAT on Udisk successful.\n"); 384 } 385 else 386 { 387 rt_kprintf("Mount FAT on Udisk failed.\n"); 388 } 389 } 390 391 break; 392 } 393 } 394 395 rt_free(sector); 396 397 return RT_EOK; 398 } 399 400 /** 401 * This function will be invoked when usb disk plug out is detected and it would clean 402 * and release all udisk related resources. 403 * 404 * @param intf the usb interface instance. 405 * 406 * @return the error code, RT_EOK on successfully. 407 */ 408 rt_err_t rt_udisk_stop(struct uhintf* intf) 409 { 410 int i; 411 ustor_t stor; 412 struct ustor_data* data; 413 414 /* check parameter */ 415 RT_ASSERT(intf != RT_NULL); 416 RT_ASSERT(intf->device != RT_NULL); 417 418 stor = (ustor_t)intf->user_data; 419 RT_ASSERT(stor != RT_NULL); 420 421 for(i=0; i<stor->dev_cnt; i++) 422 { 423 rt_device_t dev = &stor->dev[i]; 424 data = (struct ustor_data*)dev->user_data; 425 426 /* unmount filesystem */ 427 dfs_unmount(UDISK_MOUNTPOINT); 428 429 /* delete semaphore */ 430 rt_sem_delete(data->part.lock); 431 udisk_free_id(data->udisk_id); 432 rt_free(data); 433 434 /* unregister device */ 435 rt_device_unregister(&stor->dev[i]); 436 } 437 438 return RT_EOK; 439 } 440 441 #endif 442 443