在c

时间:2016-03-11 21:30:07

标签: c macos kernel ascii hex

我正在使用手机的Android rom,我想让内核从设备的NV分区加载wifi MAC地址。我的代码如下所示:

#include <linux/kernel.h>
#include <linux/random.h>
#include <linux/syscalls.h>


#define ETHER_ADDR_LEN    6
#define FILE_WIFI_MACADDR "/dev/block/mmcblk0p7"

static int bcm_wifi_get_mac_addr(unsigned char *buf)
{
int ret = 0;

mm_segment_t oldfs;
int i;
int fp;
int macbyte;
int readlen = 0;
uint rand_mac;
static unsigned char mymac[ETHER_ADDR_LEN] = {0,};
const unsigned char nullmac[ETHER_ADDR_LEN] = {0,};
const unsigned char bcastmac[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

if (buf == NULL)
    return -EAGAIN;

memset(buf, 0x00, ETHER_ADDR_LEN);

oldfs = get_fs();
set_fs(get_ds());

fp = sys_open(FILE_WIFI_MACADDR, O_RDONLY, 0);
if (fp < 0) {
    pr_err("%s: Failed to read error %d for %s\n",
            __FUNCTION__, fp, FILE_WIFI_MACADDR);
    goto random_mac;
}

for (i = 0; i<12; i++) {
macbyte=0;
    sys_lseek( fp,i+7680,SEEK_SET);
readlen = sys_read(fp,&macbyte,1);
    if (i)
        sprintf(macaddr,"%s%c",macaddr,macbyte);
    else
        sprintf(macaddr,"%c",macbyte);
}
if (readlen > 0) {
    unsigned char* macbin;
    macbin = (unsigned char*)macaddr;
    pr_info("%s: READ MAC ADDRESS %02X:%02X:%02X:%02X:%02X:%02X\n",
            __FUNCTION__,
            macbin[0], macbin[1], macbin[2],
            macbin[3], macbin[4], macbin[5]);

    if (memcmp(macbin, nullmac, ETHER_ADDR_LEN) == 0 ||
            memcmp(macbin, bcastmac, ETHER_ADDR_LEN) == 0) {
        sys_close(fp);
        goto random_mac;
    }
    memcpy(buf, macbin, ETHER_ADDR_LEN);
} else {
    sys_close(fp);
    goto random_mac;
}

sys_close(fp);
return ret;

random_mac:
set_fs(oldfs);

pr_debug("%s: %p\n", __func__, buf);

if (memcmp( mymac, nullmac, ETHER_ADDR_LEN) != 0) {
    /* Mac displayed from UI is never updated..
       So, mac obtained on initial time is used */
    memcpy(buf, mymac, ETHER_ADDR_LEN);
    return 0;
}

srandom32((uint)jiffies);
rand_mac = random32();
buf[0] = 0x00;
buf[1] = 0x90;
buf[2] = 0x4c;
buf[3] = (unsigned char)rand_mac;
buf[4] = (unsigned char)(rand_mac >> 8);
buf[5] = (unsigned char)(rand_mac >> 16);

memcpy(mymac, buf, 6);

pr_info("[%s] Exiting. MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
        __FUNCTION__,
        buf[0], buf[1], buf[2], buf[3], buf[4], buf[5] );

return 0;

}

想法是加载位于/dev/block/mmcblk0p7的nv分区,然后读取位于nv偏移7680的mac地址。问题是MAC地址是用十六进制写的,所以我试图用sprintf()将它打印成ASCII字符串。

    for (i = 0; i<12; i++) {
    macbyte=0;
    sys_lseek( fp,i+7680,SEEK_SET);
    readlen = sys_read(fp,&macbyte,1);
    if (i)
        sprintf(macaddr,"%s%c",macaddr,macbyte);
    else
        sprintf(macaddr,"%c",macbyte);
    }

在nv中,MAC看起来像这样:34 30 42 30 46 41 36 35 39 33 34 39,其中ASCII为40B0FA659349。但是结果MAC是34:30:42:30:46:41,它告诉我十六进制值根本没有被转换。

将十六进制值导出为ASCII字符串的正确方法是什么?我是编程的新手,我希望有人可以给我一些提示。

提前致谢。

2 个答案:

答案 0 :(得分:0)

认为这是OP的存根块:形成MAC地址的字符串版本。

我会为任何人修改,借用或窃取这个wiki。

sys_lseek( fp,i+7680,SEEK_SET);
char macaddr[100];
char *p = macaddr;
const char *sep = "";

for (i = 0; i < 12; i++) {
  unsigned char macbyte;
  int readlen = sys_read(fp, &macbyte, 1);
  if (readlen != 1) Handle_Error();
  p += sprintf(p, "%s%02X", sep, macbyte);
  sep = ":";
}

puts(macaddr);

答案 1 :(得分:0)

在循环中,您正在读取单个字节并将它们转换为十六进制字符串,而您实际需要做的是读取十六进制字符串并将其转换为字节值。除非你真的想要一个十六进制字符串,否则不需要转换。

你有12个十六进制字符代表6个字节,所以:

#define MAC_LEN 6
uint8_t macbytes[MAC_LEN] ;
for( i = 0; i < MAC_LEN; i++ ) 
{
    char hex_str[3] ;
    unsigned byte_val ;
    sys_lseek( fp, (i*2) + 7680, SEEK_SET ) ;
    readlen = sys_read( fp, hex_str, 2 ) ;
    sscanf( hex_str, "%2X", &byte_val ) ;
    macbytes[i] = (uint8_t)byte_val ) ;
}

NV中的数据已经 ASCII编码的十六进制;例如,0x34是十六进制数字'4'的ASCII代码,0x30是'0'的ASCII代码,ASCII字符对"40"一起代表单个8位整数值0x40。所以你需要的转换是ASCII到字节数组,而不是“十六进制到ASCII”(这没有语义意义)。