【问题标题】:Converting hexadecimal to ASCII in c在c中将十六进制转换为ASCII
【发布时间】:2016-06-27 07:19:28
【问题描述】:

我正在为手机开发 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 字符串的正确方法是什么?我是编程新手,希望有人能给我一些建议。

提前致谢。

【问题讨论】:

  • 这个问题可能更适合Stack Overflow
  • sprintf(macaddr,"%s%c",macaddr,macbyte); 是一种 UB 连接方式。最好避免。

标签: c macos kernel ascii hex


【解决方案1】:

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

你有 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”(这没有语义意义)。

【讨论】:

  • 嘿。我想知道为什么我的循环失败了?看看这个codehere 是 nv 文件的转储。如果我使用 gcc 将代码编译成可执行文件并将其放在与 nv.img 文件相同的目录中,它会成功读取 MAC 地址并以 ASCII 格式打印。您的解决方案效果很好,我只是好奇。
  • 我想我已经解释过了。我添加了进一步的解释。您可能应该编辑问题和/或标题以反映所需的转换是 ASCII 到字节数组的事实。
【解决方案2】:

认为这是 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-22
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-02
    • 1970-01-01
    相关资源
    最近更新 更多