带U盘功能的的USB接口设备已经越来越常见了。如果能够把产品说明书或者产品设备驱动程序做成一个USB CDROM,那该多方便。假设:你已经有了USB mass storage驱动。你的任务是在此基础上增加一个USB CDROM。请在手边准备好:USB2.0协议,Mass storage协议,SCSI协议(可以忽略)。此外,你需要一个debug工具:bushound。   
  步骤:
        1,制作CDROM image文件;
        2,处理usb device request:Get Max Lun
        3,处理SCSI命令:
                        INQUIRY_CMD,
                        READ_TOC_CMD,
                        MODE_SENSE6_CMD,
                        MODE_SENSE10_CMD,
                        READ6_CMD,
                        READ10_CMD
  OK. Let's go!
      
  一、制作CDROM image文件:

  google一个PC工具,比如UltraISO,把你需要出现在光盘上的东东统统塞到一个CDROM image文件里面去。然后把此文件放到你的文件系统里去。
     A:什么?你木有文件系统?!这么土?
     B:就这么土!
     A:那就放到一个大的const数组里。
     B:呃...为什么放在const?
     A:真不知道?
     B:真的...
     A:打屁屁!
 
  二、处理从control out endpoint发来的usb device request: "Get Max Lun"(bRequest等于254,usbmassbulk_10.pdf, page 7 )此命令在setup阶段收到,主要是向host报告usb mass storage Logic Unit Num。注意Num=总数-1:比如1个U盘和1个CDROM,总数为2,应该向host报告2-1=1。这样枚举后,PC出现2个盘符。

  三、处理如下几条Command Block Wrapper里的SCSI命令。
  setup成功后,SCSI命令经过CBW打包,就可以通过BULK OUT端点发送到设备了(参见usbmassbulk_10.pdf, page 13)。SCSI命令处理流程参考usbmassbulk_10.pdf figure1.尤其需要注意的是,一定不要忘记发送CSW!    
B: host发给U盘和USB CDROM的命令都是通过CBW进行的。那么怎么知道哪个命令发给U盘,哪个是给USB CDROM的呢?
A: very good question!请查看usbmassbulk_10.pdf, page 13,table5.1。在本案中CBW的bCBWLUN会给你两个值:0和1。至于0代表光盘或者1代表光盘,你的地盘你做主。
       
Go on...
    
    SCSI命令在CBW的bCBWCB头一个字节。SCSI命令很多,但是USB CDROM只需要关注这几个SCSI命令:
    INQUIRY_CMD(0x12):“报告老大,我是光盘!”。把usbcdrom_inquiry_data返回给host,注意第一个字节0x05表示CDROM,这样在PC看到的盘符就是光盘。请按照实际需要修改如下数据结构。

char usbcdrom_inquiry_data[] = {
        0x05,                /*= 5 for CDROM; 0 for usb mass storage */
        0x80,                /*= RMB BYTE is set by inquiry data */
        0x02,                /* ANSI SCSI 2 */
        0x00,                /*= Data format = 0,  */
        0x33,                /*= Additional length   */
        0x00, 0x00, 0x00,    /* Manufacturer = SOMwireless.com */
        'S', 'O', 'M', 'w', 'i', 'r', 'e', 'l', 'e', 's', 's', '.', 'c', 'o', 'm', 0x20,    /* Product = ISO9660 Image */
        0x49, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x20, 0x20,  /* Revision = 2.31 for new transparent command */
        0x32, 0x2E, 0x33, 0x31,
        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
        0x20,0x20,0x20,0x20
    };

READ_TOC_CMD(0x43):  “报告!目录结构(TOC,Table Of Content)是。。。把usbcdrom_read_toc_data返回给host。照抄就行了,不用修改。详情参见the f*cking scsi spec。你也可以用光驱读只有一个track的CDROM,用bushound抓包分析。

char usbcdrom_read_toc_data[] = {
            0x00,
            0x12,                  /*number of bytes below */
            0x01,                  /* first track */
            0x01,                  /* last track */
            0x00,                  /*reserved*/
            0x14,                  //(adr, control)
            0x01,                  //(track being described)
            0x00,                  //(reserved)
            , , , ,        // (start logical block address 0)
            0x00,                //(reserved)
            0x14,                //(adr, control)
            0xAA,                // (track being described (leadout))
            0x00,                //(reserved)
            , , 0xA2, 0x8A  //(start logical block address 41610)
    };

  SCSI设备是按照BLOCK来组织的。我们的USB虚拟光驱只是一个文件,是虚拟的CDROM。可以按照实际需要定义BLOCK大小(通常是512的整数倍),比如#define CDROM_BLOCK 512,假设我们的CDROM image文件大小为iso_image_len,那么总的BLOCK数量是block_num = (cdr_iso_len + CDROM_BLOCK - 1)/CDROM_BLOCK。在SCSI系统中,BLOCK总是从0开始编号的,那么最后一个BLOCK号block_last = block_num - 1;
    
    ok.我们来继续看看这些SCSI命令。    
    MODE_SENSE6_CMD(0x1A):
    MODE_SENSE10_CMD(0x5A):
    READ_CAPACITY_CMD(0x25):主要向host报告block_last和CDROM_BLOCK滴,只是细节各有不同。
    请注意:SCSI系统采用大端(big endian),通常ARM编译器都将代码编译成小端(little endian),需要把block_last和CDROM_BLOCK变成大端。
    
    USBSDMS_READ_CAPACITY_CMD需要返回的数据结构如下:

struct read_cap_data
    {
        unsigned long block_last;  //the last block number
        unsigned long block_len;   //in bytes
    } ;

MODE_SENSE6_CMD需要返回的数据结构如下:

struct mode_sense6_data
{
    char  length;               //sizeof( struct mode_sense6_data )
    char  media_type;           //0x05 for CDROM, 0x00 for U disk
    char  device_specific;      //0x00
    char  block_descriptor_len; //sizeof( block_last ) + sizeof( block_len )
    unsigned long block_last;   //the last block number
    unsigned long block_len;    //in bytes
} ;

MODE_SENSE10_CMD需要返回的数据结构如下:

struct mode_sense10_data
{
   unsigned short  length;                    //sizeof( struct mode_sense10_data )
   char  media_type;                          //0x05 for CDROM, 0x00 for U disk
   char  write_protect;                       //0x00
   unsigned short  reserved;                  //0x0000
   unsigned short  block_descriptor_len;      //sizeof( block_last ) + sizeof( block_len )
   unsigned long block_last;                  //the last block number
   unsigned long block_len;                   //in bytes
} ;

好了,现在插入USB(这个词很邪恶~~~~~~)
    
    ~~~~~~~~~~~~~~~~~~~~~~~~~昏哥线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    老婆,出来看神仙啦~~~~如果你很杯具,神仙木有出来Orz...那就用bushoud
    抓数据包,对照你手边的f*cking spec...blablabla...
    ~~~~~~~~~~~~~~~~~~~~~~~~~昏哥~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    Voila~~~~~~
    到此为止,你已经成功将大象装进冰箱了。
    下一步要把大象从冰箱里面取出来!
    
    需要处理的SCSI命令是:
    READ6_CMD(0x08):
    READ10_CMD(0x28):都是读操作,只是细节略有不同,详见SCSI手册。host传过来的主要参数是:起始的Block号,以及需要读取的block数(注意:不是字节数)。
    按照要求传给host就ok了。
    
    ~~~~~~~~~~~~~~~~~~~~~~~~~昏哥~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    DONE!

嵌入式系统USB CDROM虚拟光驱驱动程序开发的更多相关文章

  1. 基于 USB 传输的针式打印机驱动程序开发

    1.引言 针式打印机曾经在相当长的一段时间占据打印机市场的主导地位,但是近年来由于喷墨.激光等非击打式打印机的冲击,针式打印机的市场份额逐年下降.即便如此,由于针式打印机在票据打印领域的不可取代性,同 ...

  2. 嵌入式系统Linux内核开发工程师必须掌握的三十道题(转)

    嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...

  3. 热烈庆祝华清远见2014嵌入式系统(Linux&Android)开发就业培训课程全面升级

    近日,华清远见公开宣布:2014嵌入式系统 (Linux&Android)开发就业培训课程再次升级!据悉,华清远见如今已经持续10年,一直保持课程每年2次的更新的频率.华清远见的每 次课程更新 ...

  4. 安装Win7或者XP系统用虚拟光驱加载Win7或者XP镜像 iso文件xp win7wim文件

    安装Win7或者XP系统用虚拟光驱加载Win7或者XP镜像 iso文件xp win7wim文件 http://pcedu.pconline.com.cn/teach/xt/1201/2657834_8 ...

  5. 嵌入式系统WinCE下应用程序GUI界面开发【转】

    嵌入式系统WinCE下应用程序GUI界面开发 ByToradex 秦海 本文旨在介绍嵌入式系统在Wince下进行GUI应用程序开发可以选择的不同GUI开发框架(Framework),目前最常用的几种方 ...

  6. C、C++、boost、Qt在嵌入式系统开发中的使用

    概述 嵌入式系统开发相对来说属于偏底层的开发,也就是与硬件结合比较紧密,只能使用C/C++语言.对于做平台开发的人来说,C语言真的是很"古老"的语言,属于操作系统语言!好多人会觉得 ...

  7. Linux嵌入式系统与硬件平台的关系

    一. Linux嵌入式系统 操作系统是一种在计算机上运行的软件,它的主要任务是管理计算机上的系统资源,为用户提供使用计算机及其外部设备的接口.它存在的目的是为了管理所有硬件资源,并且提供应用软件一个合 ...

  8. Vmware中Ubuntu挂ISO到虚拟光驱

    Ubuntu 下挂ISO到虚拟光驱的方法 https://i.cnblogs.com/EditPosts.aspx?opt=1 如果要ubuntu找到rpm软件包,需要把iso挂载到/media/cd ...

  9. 嵌入式系统基础知识(一): 系统结构和嵌入式Linux

    目录 一. 嵌入式体系结构 二. 开发过程中的分工 三. 嵌入式软件体系结构 四. 嵌入式Linux 一. 嵌入式体系结构 <嵌入式系统设计师教程>这本书的前三章脉络很清晰, 按照嵌入式系 ...

随机推荐

  1. 可变参数列表-Java SE5新特性(转)

    Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理.注意:可变参数必须位于最后一项.当可变参数个数多于一个时,必将有一个不是最后一项,所以只支持 ...

  2. RFC 2327--SDP

    Network Working Group M. Handley Request for Comments: 2327 V. Jacobson Category: Standards Track IS ...

  3. exe可执行程序及堆栈分配(转载)

    可执行程序的内存分布 GNU编译器生成的目标文件默认格式为elf(executive linked file)格式,这是Linux系统所采用的可执行链接文件的通用文件格式.elf格式由若干个段(sec ...

  4. How to run OFBiz as a Service on linux

    Windows See this specific guide: How to Run OFBiz as Windows Service with Java Service Wrapper Linux ...

  5. [转] Hive 内置函数

    原文见:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF 1.内置运算符1.1关系运算符 运算符 类型 说明 A ...

  6. 游标的使用实例(Sqlserver版本)

    游标,如果是之前给我说这个概念,我的脑子有二个想法:1.你牛:2.我不会 不会不是理由,更不是借口,于是便要学习,本人属性喜欢看代码,不喜欢看书的人,所以嘛,文字对我没有吸引力:闲话少说啊,给大家提供 ...

  7. Direct3D 对X模型载入

    今天我们来学习Direct3D对模型的导入使用,Direct3D支持.X模型文件导入使用,.X文件是微软定义的3D模型文件格式,其中包含网格,动画,纹理等等一些信息. 目前3DS Max 和 Maya ...

  8. Hibernate(五)——面向对象查询语言和锁

    Hibernate做了数据库中表和我们实体类的映射,使我们不必再编写sql语言了.但是有时候查询的特殊性,还是需要我们手动来写查询语句呢,Hibernate框架为了解决这个问题给我们提供了HQL(Hi ...

  9. c++之 数组

    数组的定义 数组用于表示一组数值,例如: char arr[5]; 其中,arr称为"数组变量",简称"数组".它表示5个char型数据,我们把每一个数据称为一 ...

  10. 集合操作出现的ConcurrentModificationException(源码分析)

    摘要: 为了保证线程安全,在迭代器迭代的过程中,线程是不能对集合本身进行操作(修改,删除,增加)的,否则会抛出ConcurrentModificationException的异常. 示例: publi ...