Arduino 获得音量计数值-Arduino中文社区 - Powered by Discuz! Archiver

Zoologist 发表于 2018-2-19 16:09

Arduino 获得音量计数值

去年买了一个带有 USB 输出噪音计型号是WS1361,我特地去查了一下,2017年2月6日买的,然后一直拖到了最近才动手编写 Arduino 的代码。也多亏找到其他人的研究资料【参考1】,所以才比较顺利的完成解码。这部分的工作就像在解密一样,在不知道答案的情况下是一头雾水,当完成之后如释重负。同样的,USB逻辑分析在这次编写中也发挥了重要。此外,最近接触到的Windows USB分析软件对于反向工程也是很多有效果【参考2】。第一步还是抓取描述符
ConnectionStatusDeviceconnected
CurrentConfiguration1
SpeedLow(1.5 Mbit/s)
DeviceAddress2
NumberOf Open Pipes0
DeviceDescriptor WS1361
OffsetFieldSizeValueDescription
0bLength112h
1bDescriptorType101hDevice
2bcdUSB20110hUSBSpec 1.1
4bDeviceClass1FFhVendor-Specific
5bDeviceSubClass100h
6bDeviceProtocol100h
7bMaxPacketSize0108h8bytes
8idVendor216C0hVOTI
10idProduct205DCh
12bcdDevice20102h1.02
14iManufacturer101h"www.wensn.com"
15iProduct102h"WS1361"
16iSerialNumber100h
17bNumConfigurations101h
ConfigurationDescriptor 1 BusPowered, 50 mA
OffsetFieldSizeValueDescription
0bLength109h
1bDescriptorType102hConfiguration
2wTotalLength20012h
4bNumInterfaces101h
5bConfigurationValue101h
6iConfiguration100h
7bmAttributes180hBusPowered
4..0:Reserved ...00000
5:Remote Wakeup ..0.....No
6:Self Powered .0......No,Bus Powered
7:Reserved (set to one)
(bus-powered for 1.0) 1.......
8bMaxPower119h50 mA
InterfaceDescriptor 0/0 0Endpoints
OffsetFieldSizeValueDescription
0bLength109h
1bDescriptorType104hInterface
2bInterfaceNumber100h
3bAlternateSetting100h
4bNumEndpoints100h
5bInterfaceClass100h
6bInterfaceSubClass100h
7bInterfaceProtocol100h
8iInterface100h
之前的键盘鼠标的描述符对于分析非常有用,但是这次描述符在分析过程中几乎可以称作毫无用处。当然,如果非要说有什么作用的话,只是让我得知他使用了自定义的协议。第二步,使用逻辑分析仪查看抓包。这款逻辑分析仪带有USB接口,插入系统后,安装对应的驱动和应用程序可以在电脑上实时看到获得的当前音量(美中不足的是他们的软件没有数字签名,使用Windows 8/8.1/10 64位的朋友,必须禁用签名才能安装和运行起来)。抓到的关键数据如下: Get Device Descriptor(Transfer 12) -> 获取自定义数据(Transfer 13)–> Get Device Descriptor(Transfer 14) 这样循环下去。这样的循环是他的应用程序驱动完成的。在我看来Get Device Descriptor 是毫无用处的。可能是应用程序用来确定设备是否被 remove才做的。详细分析获取数据的过程 Transfer 13, 由 Transaction 283/286/287 三笔来组成。Transaction 283用户自定义的 Setup 过程,我们代码只需要做出和他内容相同的发出去即可。然后Transaction 286 是噪音计回复的数据包,其中有我们需要的当前音量数据。具体格式从【参考1】可以看到。硬件方面使用的是 Arduino USB Host板+ Arduino Uno,因为是 Shield板,直接插上即可使用。为了更清楚的展示接收数据的过程,我使用了巨大的LED数码管(1.8寸),关于这个数码管的介绍可以在之前的文章中找到。根据上述内容,编写程序如下:#include "Usb.h"



USB   Usb;



uint16_t LastDB=0;



void digitalshow(int value)

{

   //这是数码管要求的数据头信息

    Serial.write(0xff);

    Serial.write(0x00);

    Serial.write(0x04);//显示四位数值



    //下面是四位当前值

   

    Serial.write(0x10);//第一位黑

    Serial.write((value - value /1000 * 1000) / 100);

//第三位后面有小数点,最高位为 1 表示显示小数点

    Serial.write((value - value /100 * 100) / 10+ 0x80);

    Serial.write(value % 10);

   

   //最后一位是亮度

   Serial.write(1);

}

void DataParser(UsbDevice *pdev)

{

int nbytes=4;

uint8_t value;



Usb.ctrlReq(

          pdev->address.devAddress,

          0, //EndPoint

          0xC0, //bmRequestType

          0x04, //bRequest

          0x01, //wValeLow

          0x00, //wValueHigh

          0x0000, //wIndex

          nbytes,

          nbytes,

          &value,

          NULL);

if ((value+(value<<8))==LastDB) {

       return;

    }

else

    LastDB=(value+(value<<8));         

//Serial.print("RAW:");

//Serial.print(value,HEX);      

//Serial.print(" ");

//Serial.println(value,HEX);



//Serial.print(" DB:");

//Serial.println((value + ((value & 3) * 256)) * 0.1 + 30);

digitalshow(((value + ((value & 3) * 256)) * 0.1 + 30)*10);

}





void setup()

{

Serial.begin( 115200 );



Serial.println("Start");



if (Usb.Init() == -1)

    Serial.println("OSC did not start.");



delay( 200 );



}



void loop()

{

Usb.Task();



if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )

{

      Usb.ForEachUsbDevice(&DataParser);

      delay(200);

}

}工作的视频可以在知乎专栏看到 https://zhuanlan.zhihu.com/p/33877460 参考:1.   https://www.ebswift.com/reverse-engineering-spl-usb.htmlReverse Engineering the USB Protocol on the WENSN WS1361 Sound Pressure LevelMeter2.   http://www.lab-z.com/usblyzer/介绍一个 USB分析软件Usblyzer

MACE 发表于 2018-3-30 10:15

请问楼主,表格里彩色的USB数据是怎么弄得呢

Zoologist 发表于 2018-3-30 17:05

MACE 发表于 2018-3-30 10:15
请问楼主,表格里彩色的USB数据是怎么弄得呢

这是 usb 逻辑分析仪抓取的数据,

具体你可以看看之前的文章

lehere 发表于 2018-4-2 22:18

我也说一句在不知道答案的情况下是一头雾水,当完成之后如释重负。感同身受
页: [1]
查看完整版本: Arduino 获得音量计数值