前言
相信很多jy都对ethtool这个工具不陌生。那为什么还要再写一个将mac地址刷写进eeprom的小工具呢?因为并不是所有设备都能适配这些通用工具,工具也是要为具体的需求服务的。
工具实现愿景
基础版:命令行模式
以下为工具的可选参数(mac地址为必填项),如未指定则使用默认从参数
-b, --bus I2C总线
-a, --addr 外设地址
-o, --offset 偏移后的起始位置
-m, --mac 首个MAC地址,支持两种形式的输入,形如: `1a2b3c112233` or `1a:2b:3c:11:22:33`)
-c, --count MAC地址个数,每写一个MAC地址自增1
-i, --interval 两个MAC地址的间隔,默认0
-h, --help 打印上述选项
进阶版
增加可视化的交互界面
实现思路
刷写原理
这个问题的实质是:利用什么协议来进行数据传输? 在一些很简单的硬件设备中,不支持高级协议,所以在之前的文章中介绍过的、只需要两根线(如果加上地线就是三根)的i2c协议是一个不错的选择。
在本项目中可以用<linux/i2c.h>、<linux/i2c-dev.h>这两个i2c开源库。
各环节的具体实现方案
从全流程来看:
- 数据输入:命令行参数可使用getopt这个库来接收。
//全局变量定义
static const struct option longopts[] = {
{"bus", required_argument, NULL, 'b'},
{"addr", required_argument, NULL, 'a'},
{"offset", required_argument, NULL, 'o'},
{"mac", required_argument, NULL, 'm'},
{"count", required_argument, NULL, 'c'},
{"interval", required_argument, NULL, 'i'},
{"help", no_argument, NULL, 'h'},
{GETOPT_NULL_LONGOPT},
};
static const char *const shortopts = "+b:a:o:m:c:i:h";
//main函数中
int optc, opti;
for (;;)
{
optc = getopt_long(argc, argv, shortopts, longopts, &opti);
if (optc < 0)
break;
switch (optc)
{
case 'b':
setBus(optarg);
break;
case 'a':
setPaddr(optarg);
break;
case 'o':
setOffset(optarg);
break;
case 'm':
setMacaddr(optarg);
break;
case 'c':
setMaccnt(optarg);
break;
case 'i':
setIndex(optarg);
break;
case 'h':
print_help();
return 0;
default:
abort();
}
}
- 数据校验:在本项目中,要对参数进行合法性校验,比如输入的mac地址需符合规定格式,这可以用正则表达式来辅助判断
regex pattern("(^[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}:?[A-Fa-f\\d]{2}$)");
string str = option;
std::regex e(":");
smatch result;
bool ret = regex_match(str, result, pattern);
if (!ret)
cout << "mac address format error!";
- 算法核心:这是项目的核心逻辑,要完成的任务包括但不限于:接收参数后对相关属性进行赋值(要先进行数据清洗和转换)、调用并封装i2c库进行数据刷写、编写代码使得对底层寄存器的数值写入符合项目要求等等。
由于某些原因,这里不方便展示核心代码,对这方面感兴趣的uu可以自行上网搜索i2c库的相关调用代码并且将它修改为合适项目需求的样子。
大家只需要记住一点:
刷写的本质就是往寄存器写数据。
这一点想通之后再抽象的需求也会变得明朗。
界面(可选)
为了更好地适配不同的操作系统,小工具不采用web端或者高级桌面应用框架进行开发,而是采用基于命令行的工具whiptail
它的开发过程很简单。这个只是一个界面,作用是接收参数并传入真正的可执行程序。 以下以本程序的必选参数macaddr为例,读者可以自行添加其他选项的输入页面、增加用户欢迎页等等,参考文档详见参考资料[2]
macaddr=$(whiptail --inputbox "首个MAC地址" 10 60 1a2b3c112233 3>&1 1>&2 2>&3)
./mac -m $macaddr