2016-03-11 2 views
1

Я работаю над мобильным телефоном Android, и я хочу, чтобы ядро ​​загрузило MAC-адрес wifi из раздела NV в устройстве. Мой код выглядит следующим образом:Преобразование шестнадцатеричного в ASCII в c

#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; 

}

Идея заключается в том, чтобы загрузить Nv parition, расположенный в /dev/block/mmcblk0p7, затем прочитать MAC-адрес, который находится по смещению 7680 на NV. Проблема в том, что MAC-адрес написан в шестнадцатеричном виде, поэтому я пытаюсь распечатать его в строке ASCII, используя sprintf().

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); 
    } 

В Н.В. MAC выглядит примерно так: 34 30 42 30 46 41 36 35 39 33 34 39, который в ASCII является 40B0FA659349. Но вместо этого полученный MAC-адрес равен 34:30:42:30:46:41, который говорит мне, что шестнадцатеричные значения вообще не преобразуются.

Каким образом можно экспортировать шестнадцатеричные значения в строку ASCII? Я новичок в программировании, и я надеялся, что кто-то сможет дать мне несколько советов.

Заранее спасибо.

+1

Этот вопрос, вероятно, лучше подходит для [так]. – 5gon12eder

+1

'sprintf (macaddr,"% s% c ", macaddr, macbyte);' - способ конкатенации UB. Лучше всего избегать. – chux

ответ

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 является кодом ASCII для шестнадцатеричной цифры '4' и 0x30, что для '0', а также пара символов ASCII "40" представляет единственное 8-битное целочисленное значение 0x40. Таким образом, вам потребуется преобразование ASCII в байтовый массив, а не «hex to ASCII» (что не имеет смыслового смысла).

+0

Это сработало отлично! Спасибо огромное! –

+0

Эй. Я хотел бы знать, почему именно моя петля терпит неудачу? Посмотрите на этот [код] (https://codeshare.io/DjTsz). И [здесь] (http://www.mediafire.com/download/h7h0t53oqs2iboz/nv.img) - это дамп файла nv. Если я завершу код в исполняемый файл с gcc и поместил его в тот же каталог, что и файл nv.img, он успешно прочитал MAC-адрес и распечатал его в формате ASCII. Ваше решение отлично работает, мне просто интересно. –

+0

Я думаю, что я уже объяснил это. Я добавил дополнительные объяснения. Вероятно, вы должны отредактировать вопрос и/или заголовок, чтобы отразить тот факт, что требуется преобразование ASCII в байтовый массив. – Clifford

0

I думаю это блок прерывания OP: формирование строковой версии MAC-адреса.

Я сделаю эту вики для кого-либо, чтобы изменить, взять или украсть.

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); 
Смежные вопросы