make UDisk work well

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2448 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
sc943313837@gmail.com 2012-11-25 16:00:28 +00:00
parent 60c27fc4b5
commit 9789907ca1
1 changed files with 106 additions and 81 deletions

View File

@ -10,6 +10,7 @@
* Change Logs:
* Date Author Notes
* 2012-10-01 Yi Qiu first version
* 2012-11-25 Heyuanjie87 reduce the memory consumption
*/
#include <rtthread.h>
@ -22,6 +23,7 @@
#define STATUS_CBW 0x00
#define STATUS_CSW 0x01
#define STATUS_RECEIVE 0x02
#define STATUS_SEND 0x03
static uclass_t mstorage;
static uep_t ep_in, ep_out;
@ -30,6 +32,8 @@ static rt_uint8_t *write_ptr;
static int status = STATUS_CBW;
static struct ustorage_csw csw;
static rt_device_t disk;
static rt_uint32_t _block;
static rt_uint32_t _count, _size;
static struct rt_device_blk_geometry geometry;
static struct udevice_descriptor dev_desc =
@ -222,28 +226,32 @@ static rt_err_t _read_capacity(udevice_t device)
*/
static rt_err_t _read_10(udevice_t device, ustorage_cbw_t cbw)
{
rt_uint32_t block;
rt_uint32_t count;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(cbw != RT_NULL);
block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
cbw->cb[5]<<0 ;
_block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
cbw->cb[5]<<0 ;
count = cbw->cb[7]<<8 | cbw->cb[8]<<0 ;
_count = cbw->cb[7]<<8 | cbw->cb[8]<<0 ;
RT_ASSERT(count < geometry.sector_count);
RT_ASSERT(_count < geometry.sector_count);
rt_device_read(disk, block, buffer, count);
dcd_ep_write(device->dcd, ep_in, buffer, count * geometry.bytes_per_sector);
rt_device_read(disk, _block, buffer, 1);
dcd_ep_write(device->dcd, ep_in, buffer, geometry.bytes_per_sector);
_count --;
if (_count)
{
_block ++;
status = STATUS_SEND;
}
else
{
status = STATUS_CSW;
}
return RT_EOK;
}
static rt_uint32_t _block;
static rt_uint32_t _count, _size;
/**
* This function will handle write_10 request.
*
@ -258,14 +266,14 @@ static rt_err_t _write_10(udevice_t device, ustorage_cbw_t cbw)
RT_ASSERT(cbw != RT_NULL);
_block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
cbw->cb[5]<<0 ;
cbw->cb[5]<<0 ;
_count = cbw->cb[7]<<8 | cbw->cb[8]<<0;
csw.data_reside = cbw->xfer_len;
_size = _count * geometry.bytes_per_sector;
write_ptr = buffer;
RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x 0x%x\n",
_count, geometry.sector_count));
_count, geometry.sector_count));
dcd_ep_read(device->dcd, ep_out, buffer, MIN(_size, 4096));
@ -302,6 +310,21 @@ static rt_err_t _ep_in_handler(udevice_t device, rt_size_t size)
status = STATUS_CBW;
dcd_ep_read(device->dcd, ep_out, ep_out->buffer, SIZEOF_CBW);
}
if(status == STATUS_SEND)
{
rt_device_read(disk, _block, buffer, 1);
dcd_ep_write(device->dcd, ep_in, buffer, geometry.bytes_per_sector);
_count --;
if (_count)
{
_block ++;
status = STATUS_SEND;
}
else
{
status = STATUS_CSW;
}
}
return RT_EOK;
}
@ -378,7 +401,6 @@ static rt_err_t _ep_out_handler(udevice_t device, rt_size_t size)
break;
case SCSI_READ_10:
_read_10(device, cbw);
status = STATUS_CSW;
break;
case SCSI_WRITE_10:
_write_10(device, cbw);
@ -392,7 +414,7 @@ static rt_err_t _ep_out_handler(udevice_t device, rt_size_t size)
else if(status == STATUS_RECEIVE)
{
RT_DEBUG_LOG(RT_DEBUG_USB, ("write size 0x%x block 0x%x oount 0x%x\n",
size, _block, _size));
size, _block, _size));
_size -= size;
write_ptr += size;
@ -464,11 +486,14 @@ static rt_err_t _class_run(udevice_t device)
RT_DEBUG_LOG(RT_DEBUG_USB, ("mass storage run\n"));
disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
RT_ASSERT(disk != RT_NULL);
if(disk == RT_NULL)
return RT_ERROR;
if(rt_device_control(disk, RT_DEVICE_CTRL_BLK_GETGEOME, (void*)&geometry) != RT_EOK)
return RT_ERROR;
buffer = (rt_uint8_t*)rt_malloc(RT_USB_MSTORAGE_BUFFER_SIZE);
rt_device_control(disk, RT_DEVICE_CTRL_BLK_GETGEOME, (void*)&geometry);
buffer = (rt_uint8_t*)rt_malloc(geometry.bytes_per_sector);
if(buffer == RT_NULL)
return RT_ERROR;
dcd_ep_read(device->dcd, ep_out, ep_out->buffer, SIZEOF_CBW);
return RT_EOK;
@ -525,7 +550,7 @@ uclass_t rt_usbd_class_mstorage_create(udevice_t device)
/* create an alternate setting */
setting = rt_usbd_altsetting_create(&mass_desc.intf_desc,
sizeof(struct umass_descriptor));
sizeof(struct umass_descriptor));
/* add the bulk out and bulk in endpoint to the alternate setting */
rt_usbd_altsetting_add_endpoint(setting, ep_out);