在对物联网产品开发测试的过程中,需要对无线射频芯片配置mac地址,
以高通 ATHEROS AR93XX为例, 硬件mac地址存放于uboot的一个固定地址中.
在openwrt中可以开发setmac程序来配置.
/**
* create by iversondeng168
*/
#include <sys/time.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <syslog.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <memory.h>
#include <signal.h>
#define UI8 unsigned char
#define I8 char
#define U32 unsigned int
#define I32 int
#define UBOOT_MACADDR (0x1fc00)
I32 hex_char_to_int(I8 in)
{
if(in >= '0' && in <= '9')
return in - '0';
if(in >= 'a' && in <= 'f')
return (in - 'a') + 10;
if(in >= 'A' && in <= 'F')
return (in - 'A') + 10;
return 0;
}
I8* cmd_system(const I8* command)
{
I8* result = "";
FILE *fpRead;
fpRead = popen(command, "r");
I8 buf[1024];
memset(buf,'\0',sizeof(buf));
while(fgets(buf,1024-1,fpRead)!=NULL)
{
result = buf;
}
if(fpRead!=NULL)
pclose(fpRead);
return result;
}
void set_wifissid(UI8*suffix)
{
I8*retpt;
I8 cmds[128]={0};
//wifi ap模式才需要设置ssid
retpt = cmd_system("uci get wireless.@wifi-iface[0].mode");
if(strncmp("ap",retpt,2)) return;
sprintf(cmds,"uci set wireless.@wifi-iface[0].ssid=OpenWrt-%02X%02X%02X",suffix[0],suffix[1],suffix[2]);
cmd_system(cmds);
cmd_system("uci commit wireless");;
}
void set_macaddr(UI8*data,I32 datalen)
{
if(datalen != 6) return;
UI8 macaddr[6];
memset(macaddr,0,6);
memcpy(macaddr,data,6);
//macaddr 第一个字节的第二位必须是偶数(0、2、4、6、8、A、C、E)
//经过测试mac不能全为0
if(macaddr[0] % 2 != 0) return;
if(macaddr[0] == 0 && macaddr[1] == 0 && macaddr[2] == 0 &&
macaddr[3] == 0 && macaddr[4] == 0 && macaddr[5] == 0)
return;
//拷贝一份uboot
cmd_system("dd if=/dev/mtd0 of=/tmp/new_uboot.bin");
sleep(1);
I8*newubootpath = "/tmp/new_uboot.bin";
//检测副本存在并且可读可写
while(access(newubootpath,F_OK | R_OK | W_OK) == -1);
//将mac地址写入副本固件中
I32 new_fd = open(newubootpath,O_RDWR);
if(new_fd < 0) return;
//0x1fc00即为mac起始地址
lseek(new_fd,UBOOT_MACADDR,SEEK_SET);
write(new_fd,macaddr,6);
close(new_fd);
//附带设置wifi名称
set_wifissid(&macaddr[3]);
sleep(1);
//将副本写入分区会自动重启,openwrt重启后会自动清理掉/tmp下的文件
cmd_system("mtd -r write /tmp/new_uboot.bin u-boot");
}
//setmac auto / setmac AUTO
//setmac 001234567890
I32 main(I32 argc,I8*argv[])
{
UI8 i;
UI8 j;
UI8 macaddr[6];
memset(macaddr,0,sizeof(macaddr));
srand(time(NULL));
if(argc != 2){
printf("argc != 2\n");
return -1;
}
if(!strcmp("auto",argv[1]) ||
!strcmp("AUTO",argv[1]))
{
sleep(1);
macaddr[0] = 0x00;
for(i=1;i < sizeof(macaddr);i++)
{
macaddr[i] = rand() & 0xFF;
}
}
else{
if(strlen(argv[1]) != 12)
{
printf("macadddr format error!\n");
return -1;
}
for(i=0,j=0;i < sizeof(macaddr);i++,j+=2)
{
macaddr[i] = hex_char_to_int(argv[1][j]) * 16 + hex_char_to_int(argv[1][j + 1]);
if(macaddr[0] % 2 != 0){
printf("the macaddr head must be even number\n");
return -1;
}
}
}
printf("set macaddr=%02X:%02X:%02X:%02X:%02X:%02X\n",macaddr[0],macaddr[1],macaddr[2],macaddr[3],macaddr[4],macaddr[5]);
set_macaddr(macaddr,sizeof(macaddr));
return 0;
}
执行交叉编译
GCC=/home/openwrt-master/staging_dir/toolchain-mips_74kc_gcc-5.3.0_musl-1.1.16/bin/mips-openwrt-linux-gcc
$GCC setmac.c -o setmac -O2 -w