Wowwee Rovio 核心库 libNS 逆向工程

来自Jack's Lab
(版本间的差异)
跳转到: 导航, 搜索
(以“== Undocumented Rovio API == === debug.cgi === detailed information is located in 'Host/LibCamera/Src/LibIPCamera.c' <pre> http://YOUR_ROVIO_IP/debug.cgi?action...”为内容创建页面)
 
 
第1行: 第1行:
== Undocumented Rovio API ==
+
== mcu_send_cmd(p1, p2, p3, p4) ==
 
+
=== debug.cgi ===
+
 
+
detailed information is located in 'Host/LibCamera/Src/LibIPCamera.c'
+
  
 
<pre>
 
<pre>
  http://YOUR_ROVIO_IP/debug.cgi?action=DEBUG_CMD[&param1=value[&param2=value[...]]]
+
char mcu_cmd[] =  
</pre>
+
 
+
DEBUG_CMD:
+
 
+
* net
+
* print
+
* pppip
+
* dppp
+
* ppp
+
* rtsp
+
* channel
+
* upnp
+
* malloc
+
* checkip
+
* ddns
+
* line
+
* uart (MCU debug)
+
* mcu
+
* break
+
* ps (wlan ps mode)
+
* cfg (set wlan sleep cfg 5)
+
* gpiob19 (set gpiob for mcu)
+
* mall (return mall info, including arena, ordblks, smblks, hblks, hblkhd, usmblks, fsmblks ... maxfree)
+
* write_mp4 [bitrate]
+
* read_flash [address, size]
+
* read_mem [address, size]
+
* write_mem [address, size, value]
+
* write_register [address, value, size]
+
* set_oe [out, dir, size]
+
* set_dat [out, dat, size]
+
* get_oe [address, value, size]
+
* read_i2c [address]
+
* write_i2c [address, value]
+
 
+
<br><br>
+
 
+
=== mcu ===
+
 
+
此为控制 mcu 的 cgi 接口
+
 
+
这个 mcu 是指驱动板上的牛屎块 MCU,其用于负责三个轮子的方向和里程计数、head 的高中低角度、head 上的 LED 灯控制、IR radar 电源和状态、电池电量检测、电源控制(电量低则切断电源),可见 Rovio 的核心控制都在这
+
 
+
主控 SoC 通过串口 /dev/ser1 和其通讯,其相关代码位于 Host/LibCamera/Src/MCU.c
+
 
+
GPIOB19 作为外部中断,用于唤醒 MCU。欲唤醒时,软件模拟一个中断脉冲即可:
+
 
+
<source lang=cpp>
+
void mcuWakeup()
+
 
{
 
{
    /* Set GPIO for MCU */
+
  0x55, 0x11, 0x4d, 0x4d, 0x00, 0x01, 0x00, 0x53, 0x48, 0x52, 0x54,
    mcuLock();
+
  0x00, 0x01, 0x00, 0x01,  p1,  p2,  p3,  p4, 0x00, 0x00, 0xaa
    outpw(REG_GPIOB_OE,inpw(REG_GPIOB_OE) & ~MCU_GPIO);  //GPIOB19 output;
+
    outpw(REG_GPIOB_DAT,inpw(REG_GPIOB_DAT) & ~MCU_GPIO); //GPIOB19 low
+
    tt_msleep(100);
+
    outpw(REG_GPIOB_DAT,inpw(REG_GPIOB_DAT) | MCU_GPIO); //GPIOB19 high
+
    tt_msleep(100);
+
    mcuUnlock();
+
 
}
 
}
</source>
 
  
 +
调用 mcuSendCommand() 或 mcuSendCommand_NoResponse() 将命令字通过写 mcu 的串口“通知”mcu 执行相应的动作
  
'''命令语法:'''
+
这两个函数定义在 Host/LibCamera/Src/MCU.c
 
+
<pre>
+
http://YOUR_ROVIO_IP/mcu?parameters=CMD_ID
+
 
</pre>
 
</pre>
  
<b>CMD_ID</b> 是一串 16 进制数字,只能有 36 个,否则会报 'responses = error_length'
 
  
貌似 CMD_ID 的 28 个前缀始终为:114d 4d00 0100 5348 5254 0001 0001
 
  
 
+
== send_drive_cmd(p1, p2) ==
==== Get Battery state ====
+
  
 
<pre>
 
<pre>
http://YOUR_ROVIO_IP/mcu?parameters=114d4d0001FF53485254000100010b000000
+
mcu_send_cmd(p1, p2, 0, 0);
 
</pre>
 
</pre>
  
上述命令结果返回 responses = 0E0100000000000000000003CB744A
 
  
最后的 74 和 4A 分别为电池的电量(<100 turn itself off; 100 ~ 106 try to go back home; 106 ~ 127 normal)和充电状态(0~79 not charging; 80 charging)
+
=== state_change_head_position(p1) ===
 
+
 
+
==== Rovio 顶灯控制 ====
+
 
+
以下命令仅适用于 Rovio 离开充电底座的情形
+
  
 
<pre>
 
<pre>
http://YOUR_ROVIO_IP/mcu?parameters=114D4D00010053485254000100011A000000    # turn off all lights
+
send_drive_cmd(0xc, p1)
http://YOUR_ROVIO_IP/mcu?parameters=114D4D00010053485254000100011AFF0000    # turn on all lights
+
 
</pre>
 
</pre>
  
命令字 114D4D00010053485254000100011A<b>XY</b>0000 中的 XY 是个 16 进制值,其与各 LED 的对应关系为:
+
参数 p1 取值:
  
  LED6 LED5 | LED4 LED3 LED2 LED1
+
0x00 head 放平
  
 
+
0xff head 抬到最高
LED 编号如下所示:
+
 
+
[[文件:Rovio-led.jpg]]
+
 
+
 
+
则 3F 就可将所有 LED 打开;0F 则 打开 LED4 ~ LED1;12 则打开 LED5 和 LED2
+
 
+
<source lang=bash>
+
#!/bin/sh
+
 
+
# LED1 0x01
+
# LED2 0x02
+
# LED3 0x04
+
# LED4 0x08
+
# LED5 0x10
+
# LED6 0x20
+
 
+
for ((c=1; c<5; c++))
+
do
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A000000" http://192.168.1.254/mcu
+
curl -u username:password -d "parameters=114D4D00010053485254000100011AFF0000" http://192.168.1.254/mcu
+
done
+
 
+
 
+
for ((c=1; c<5; c++))
+
do
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A010000" http://192.168.1.254/mcu
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A020000" http://192.168.1.254/mcu
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A040000" http://192.168.1.254/mcu
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A080000" http://192.168.1.254/mcu
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A100000" http://192.168.1.254/mcu
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A200000" http://192.168.1.254/mcu
+
done
+
 
+
for ((c=1; c<5; c++))
+
do
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A000000" http://192.168.1.254/mcu
+
curl -u username:password -d "parameters=114D4D00010053485254000100011AFF0000" http://192.168.1.254/mcu
+
done
+
 
+
sleep 1;
+
curl -u username:password -d "parameters=114D4D00010053485254000100011A3F0000" http://192.168.1.254/mcu
+
</source>
+
 
+
=== Rovio 车轮精确控制 ===
+
 
+
虽然 API 提供有 Motion Control,但无法精确控制,这个还得直接来操作 MCU
+
 
+
libNS.a 分析得知:
+
 
+
send_wheel_speed_cmd 用的命令字是:
+
 
+
1b xx xx xx
+
 
+
 
+
后面的三个字段分别代表 右轮、左轮、后轮
+
 
+
00 ~ 7F 为正转;80 ~ FF 为反转。如:1b818100 为后退,1b010100 为前进
+
 
+
 
+
send_wheel_pwm_cmd,用的命令字是:
+
 
+
17 xx xx xx
+
 
+
后面的三个字段分别代表 右轮、左轮、后轮
+
 
+
xx 取值 09 ~ 28 轮子才有明显的前进移动。后退移动则 xx 取值应在 88 ~ a8
+
  
 
<br><br>
 
<br><br>
  
== Key Control Rovio API ==
+
== send_wheel_cmd(p1, p2, p3, p4) ==
 
+
=== Movement Control ===
+
 
+
语法:
+
  
 
<pre>
 
<pre>
http://YOUR_ROVIO_IP/rev.cgi?Cmd=nav&action=value&drive=d_value&speed=s_value
+
if(p2 <= 0)
</pre>
+
  t2 = ((-p2) & 0xff) | 0x80;
 +
else
 +
  t2 = p2 & 0xff;
  
<pre>
+
if(p3 <= 0)
value = 18
+
  t3 = ((-p3) & 0xff) | 0x80;
 +
else
 +
  t3 = p3 & 0xff;
  
d_value = 0 (Stop)
+
if(p4 <= 0)
   1 (Forward)
+
   t4 = ((-p4) & 0xff) | 0x80;
  2 (Backward)
+
else
  3 (Straight left)
+
   t4 = p4 & 0xff;
  4 (Straight right)
+
   5 (Rotate left by speed)
+
  6 (Rotate right by speed)
+
  7 (Diagonal forward left)
+
  8 (Diagonal forward right)
+
  9 (Diagonal backward left)
+
  10 (Diagonal backward right)
+
  11 (Head up)
+
  12 (Head down)
+
  13 (Head middle)
+
  14 (Reserved)
+
  15 (Reserved)
+
  16 (Reserved)
+
  17 (Rotate left by 20 degree angle increments)
+
  18 (Rotate right by 20 degree angle increments)
+
  
s_value = 1 (fastest) – 10 (slowest)
+
mcu_send_cmd(p1, t2, t3, t4);
 
</pre>
 
</pre>
  
  
简单的,如下的命令实现持续前进:
+
=== send_wheel_speed_cmd(p1, p2, p3) ===
 
+
<source lang=bash>
+
  for ((i=0; i<18; i++));
+
    do curl -u username:password -d "Cmd=nav&action=18&drive=1&speed=1" http://YOUR_ROVIO_IP/rev.cgi;
+
  done
+
</source>
+
 
+
 
+
==== 摄像头抬头控制 ====
+
 
+
一般的,摄像头抬头有三个位置:低、中、高
+
 
+
其对应的命令为:
+
 
+
  /rev.cgi?Cmd=nav&action=18&drive=12
+
  /rev.cgi?Cmd=nav&action=18&drive=13
+
  /rev.cgi?Cmd=nav&action=18&drive=11
+
 
+
 
+
更精确地,通过连续执行:
+
 
+
<pre>
+
  http://YOUR_ROVIO_IP/rev.cgi?Cmd=nav&action=18&drive=11&speed=1
+
  http://YOUR_ROVIO_IP/rev.cgi?Cmd=nav&action=18&drive=0&speed=1
+
</pre>
+
 
+
可将摄像头抬高的过程改为 4 个点,视角要比原高、中、低三个点的要好,可用如下命令行实现之:
+
 
+
<source lang=bash>
+
curl -u username:password -d "Cmd=nav&action=18&drive=11&speed=1" http://YOUR_ROVIO_IP/rev.cgi &&        \
+
curl -u username:password -d "Cmd=nav&action=18&drive=0&speed=1" http://YOUR_ROVIO_IP/rev.cgi
+
</source>
+
 
+
==== Rovio 回家 ====
+
 
+
<source lang=bash>
+
curl -u username:password -d "Cmd=nav&action=13" http://YOUR_ROVIO_IP/rev.cgi
+
</source>
+
 
+
 
+
=== 获取当前图像 ===
+
 
+
<b>改变图像分辨率</b>
+
  
   /ChangeResolution.cgi?ResType=value
+
   send_wheel_cmd(0x1b, p1, p2, p3);
  
value 取 0 (176x144), 1 (352x288), 2 (320x240), 3 (640x480)
 
  
<source lang=bash>
+
=== send_wheel_pwm_cmd(p1, p2, p3) ===
curl -u username:password -d "ResType=3" http://YOUR_ROVIO_IP/ChangeResolution.cgi
+
</source>
+
  
 +
  send_wheel_cmd(0x17, p1, p2, p3);
  
<b>改变图像压缩质量</b>
 
  
  /ChangeCompressRatio.cgi?Ratio=value
+
== update_encoders() ==
  
value 取 0(低质量), 1(中等质量), 2(高质量)
 
  
  
<b>如下直接获取实时高质量图像:</b>
+
== smc_go_home() ==
  
  /Jpeg/CamImg.jpg
 
  
<source lang=bash>
 
curl -u username:password -d "ResType=3" http://YOUR_ROVIO_IP/ChangeResolution.cgi
 
curl -u username:password -d "Ratio=2" http://YOUR_ROVIO_IP/ChangeCompressRatio.cgi
 
curl -u username:password http://YOUR_ROVIO_IP/Jpeg/CamImg.jpg > realtime-img.jpg
 
</source>
 
  
 +
<br><br><br>
 +
<br><br><br>
 +
<br><br><br>
 +
<br><br><br>
 +
<br><br><br>
 
<br><br><br>
 
<br><br><br>
 
<br><br><br>
 
<br><br><br>

2014年5月24日 (六) 18:38的最后版本

目录

[编辑] 1 mcu_send_cmd(p1, p2, p3, p4)

char mcu_cmd[] = 
{
  0x55, 0x11, 0x4d, 0x4d, 0x00, 0x01, 0x00, 0x53, 0x48, 0x52, 0x54,
  0x00, 0x01, 0x00, 0x01,   p1,   p2,   p3,   p4, 0x00, 0x00, 0xaa
}

调用 mcuSendCommand() 或 mcuSendCommand_NoResponse() 将命令字通过写 mcu 的串口“通知”mcu 执行相应的动作

这两个函数定义在 Host/LibCamera/Src/MCU.c


[编辑] 2 send_drive_cmd(p1, p2)

mcu_send_cmd(p1, p2, 0, 0);


[编辑] 2.1 state_change_head_position(p1)

send_drive_cmd(0xc, p1)

参数 p1 取值:

0x00 head 放平

0xff head 抬到最高



[编辑] 3 send_wheel_cmd(p1, p2, p3, p4)

if(p2 <= 0)
  t2 = ((-p2) & 0xff) | 0x80;
else
  t2 = p2 & 0xff;

if(p3 <= 0)
  t3 = ((-p3) & 0xff) | 0x80;
else
  t3 = p3 & 0xff;

if(p4 <= 0)
  t4 = ((-p4) & 0xff) | 0x80;
else
  t4 = p4 & 0xff;

mcu_send_cmd(p1, t2, t3, t4);


[编辑] 3.1 send_wheel_speed_cmd(p1, p2, p3)

 send_wheel_cmd(0x1b, p1, p2, p3);


[编辑] 3.2 send_wheel_pwm_cmd(p1, p2, p3)

 send_wheel_cmd(0x17, p1, p2, p3);


[编辑] 4 update_encoders()

[编辑] 5 smc_go_home()


































个人工具
名字空间

变换
操作
导航
工具箱