U盘支持CDROM格式,其实是U盘中含有两个逻辑单元,即LUN。其中,一个LUN表现为CD-ROM device,另一个表现为SBC Direct-access device。而这两种格式的优缺点,及为什么要这样实现,可以自行百度。
在讲如何实现CD-ROM格式前,不得不提另一个名词,即量产工具。量产工具指的就是一个U盘设备,该设备包含了两种LUN,其中一个是你要制作的image系统,该系统被放置在CD-ROM逻辑单元,用户只能读取或者插入U盘后自动运行,另一个就是常规的U盘。制作这种特殊U盘可以到淘宝上搜索,有专门的卖家,且卖家会提供制作工具及说明文档,帮你完成量产。
我们在有了量产工具和USB Mass Storage驱动后,如果使我们的USB设备完成枚举流程且顺利的访问U盘呢?
正文
一、Get Max LUN请求
该class类的请求,可以使host端获得device端的LUN数量,这会为接下来的Inquiry提供上限。以下是FreeBSD中的代码流程:
当Host完成strandard request后,会去attach umass驱动,在umass_attach接口中,会初始化驱动的一些基本信息
umass_attach()
---> usbd_transfer_setup() /* 设置umass的传输方式为umass_bbb_config */
---> sc->sc_transform = &umass_scsi_transform /* 设置传输协议为 SCSI */
---> sc->sc_maxlun = umass_bbb_get_max_lun() /* 获取最大的 LUN */
---> umass_cam_attach_sim() /* 注册 SIM */
static uint8_t
umass_bbb_get_max_lun(struct umass_softc *sc)
{
struct usb_device_request req;
usb_error_t err;
uint8_t buf = 0;
/* The Get Max Lun command is a class-specific request. */
req.bmRequestType = UT_READ_CLASS_INTERFACE;
req.bRequest = UR_BBB_GET_MAX_LUN;
USETW(req.wValue, 0);
req.wIndex[0] = sc->sc_iface_no;
req.wIndex[1] = 0;
USETW(req.wLength, 1);
err = usbd_do_request(sc->sc_udev, NULL, &req, &buf);
if (err) {
buf = 0;
/* Device doesn't support Get Max Lun request. */
printf("%s: Get Max Lun not supported (%s)\n",
sc->sc_name, usbd_errstr(err));
}
return (buf);
}
二、完成Inquiry
三、访问U盘
在第二步中,驱动已经知道那个LUN是Direct-access device了,所以我们只需要在CBW中指定LUN为当前的值即可。
四、访问CD-ROM
在访问CD-ROM时,除了需要满足U盘的一些命令外,还需要完成READ TOC指令,格式如下:
说明:USB Mass Storage驱动具体要实现那些SCSI命令,请参考usb_msc_boot_1.0.pdf
但是该文档中对data有删减,所以SCSI返回详细数据可参考SCSI Commands Reference Manual.pdf
文章结尾推荐一个比较好的博客:
1、如何实现Linux下的U盘(USB Mass Storage)驱动
——该博客详细的介绍了U盘驱动的相关基础知识,及驱动协议之间的关系
博文链接:http://blog.csdn.net/mao0514/article/details/24996553
2、Linux USB gadget设备驱动解析(2)---驱动调试
——该文章详细的讲解了BBB传输方式下,驱动所处的状态及Wrapper的说明
文章链接:http://www.hzlitai.com.cn/article/ARM11/SYSTEM/1746.html
<<< 返回博客架构