📄 userhermes.c
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/io.h>#include <errno.h>#include <readline/readline.h>#include <readline/history.h>#include <linux/types.h>typedef __u8 uint8_t;typedef __u16 uint16_t;typedef __u32 uint32_t;#include "hermes.h"#define BAP_BUSY_TIMEOUT 50#define fatal(s) do { perror(s); exit(1); } while (0)typedef struct record_info { uint16_t rid; uint16_t len; char *name;} record_info_t;record_info_t rid_table[] = { {0xfc00, 2, "CNFPORTTYPE"}, {0xfc01, 6, "CNFOWNMACADDR"}, {0xfc02, 34, "CNFDESIREDSSID"}, {0xfc03, 2, "CNFOWNCHANNEL"}, {0xfc04, 34, "CNFOWNSSID"}, {0xfc05, 2, "CNFOWNATIMWIN"}, {0xfc06, 0, "CNFSYSSCALE"}, {0xfc07, 0, "CNFMAXDATALEN"}, {0xfc08, 0, "CNFWDSADDR"}, {0xfc09, 0, "CNFPMENABLED"}, {0xfc0a, 0, "CNFPMEPS"}, {0xfc0b, 0, "CNFMULTICASTRX"}, {0xfc0c, 0, "CNFMAXSLEEPDUR"}, {0xfc0d, 0, "CNFCNFPMHOLDDUR"}, {0xfc0e, 0, "CNFOWNNAME"}, {0xfc10, 0, "CNFOWNDTIMPER"}, {0xfc11, 0, "CNFWDSADDR1"}, {0xfc12, 0, "CNFWDSADDR2"}, {0xfc13, 0, "CNFWDSADDR3"}, {0xfc14, 0, "CNFWDSADDR4"}, {0xfc15, 0, "CNFWDSADDR5"}, {0xfc16, 0, "CNFWDSADDR6"}, {0xfc17, 0, "CNFMCASTPMBUFF"}, {0xfcb0, 0, "CNFSHORTPREAMBLE"}};#define NUM_RIDS (sizeof(rid_table) / sizeof(record_info_t))typedef struct record { uint16_t len; uint16_t type; uint16_t value[4096];} record_t;/* Set up a BAP to read a particular chunk of data from card's internal buffer. * * Returns: < 0 on internal failure (errno), 0 on success, >0 on error from firmware * * Callable from any context */static int hermes_bap_seek(ulong hw, int bap, uint16_t id, uint16_t offset){ int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0; int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0; int k; uint16_t reg; /* Paranoia.. */ if ( (offset > HERMES_BAP_OFFSET_MAX) || (offset % 2) ) return -EINVAL; /* Now we actually set up the transfer */ hermes_write_reg(hw, sreg, id); hermes_write_reg(hw, oreg, offset); /* Wait for the BAP to be ready */ k = BAP_BUSY_TIMEOUT; reg = hermes_read_reg(hw, oreg); while ( (reg & HERMES_OFFSET_BUSY) && k) { k--; reg = hermes_read_reg(hw, oreg); } if (reg & HERMES_OFFSET_BUSY) return -ETIMEDOUT; if (reg & HERMES_OFFSET_ERR) return reg; return 0;}/* Read a block of data from the chip's buffer, via the * BAP. Synchronization/serialization is the caller's problem. len * must be even. * * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware * * Callable from any context */int hermes_bap_pread(ulong hw, int bap, char *buf, uint16_t len, uint16_t id, uint16_t offset){ int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int err; err = hermes_bap_seek(hw, bap, id, offset); if (err) return err; /* Actually do the transfer */ hermes_read_data(hw, dreg, buf, len/2); return 0;}/* Write a block of data to the chip's buffer, via the * BAP. Synchronization/serialization is the caller's problem. len * must be even. * * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware * * Callable from any context */int hermes_bap_pwrite(ulong hw, int bap, const char *buf, uint16_t len, uint16_t id, uint16_t offset){ int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int err; if (len % 2) return -EINVAL; err = hermes_bap_seek(hw, bap, id, offset); if (err) return err; /* Actually do the transfer */ hermes_write_data(hw, dreg, buf, len/2); return 0;}void usage(void){ fprintf(stderr, "Usage: userprism <base io>\n"); exit(1);}char *rl_gets (void){ char * line; /* Get a line from the user. */ line = readline ("> "); /* If the line has any text in it, save it on the history. */ if (line && *line) add_history (line); return (line);}void display(unsigned long base){#define DREG(name) printf("%-16s: %04x\n", #name, inw(base + HERMES_##name)) DREG(CMD); DREG(PARAM0); DREG(PARAM1); DREG(PARAM2); DREG(STATUS); DREG(RESP0); DREG(RESP1); DREG(RESP2); DREG(INFOFID); DREG(RXFID); DREG(ALLOCFID); DREG(TXCOMPLFID); DREG(SELECT0); DREG(OFFSET0); DREG(SELECT1); DREG(OFFSET1); DREG(EVSTAT); DREG(INTEN); DREG(EVACK); DREG(CONTROL); DREG(SWSUPPORT0); DREG(SWSUPPORT1); DREG(SWSUPPORT2); DREG(AUXPAGE); DREG(AUXOFFSET); DREG(AUXDATA);#undef DREG}int read_lt(ulong base, int bap, uint16_t rid, record_t *rec){ int err; err = hermes_bap_pread(base, bap, (char *)rec, 4, rid, 0); if (err) { fprintf(stderr, "Error %d reading type/length\n", err); return err; } printf("rec->len=%d rec->type=0x%04x\n", rec->len, rec->type); err = hermes_bap_pread(base, bap, (char *)&rec->value, rec->len, rid, 4); if (err) { fprintf(stderr, "Error %d reading value (%d words)\n", err, rec->len); return err; } return 0;}voidshow_records(unsigned long base){ int i, j; record_t rec; printf("%d records total.\n", NUM_RIDS); for (i = 0; i < NUM_RIDS; i++) { record_info_t *info = &rid_table[i]; printf("Record %s [0x%04x]: expected length %04d\n", info->name, info->rid, info->len); read_lt(base, 1, info->rid, &rec); printf("Type 0x%04x, Len %04d: ", rec.type, rec.len); for (j = 0; j < rec.len; j++) printf("%04x:", rec.value[j]); printf("\n"); }}voidshow_record(unsigned long base, uint16_t rid){ record_t rec; int j; printf("RID 0x%04x: ", rid); read_lt(base, 1, rid, &rec); printf("type=0x%04x len=%04d value=\"", rec.type, rec.len); for (j = 0; j < rec.len/2; j++) printf("%04x:", rec.value[j]); printf("\"\n");}void do_line(unsigned long base, const char *line){ char reg[100]; int off; int val; int n; n = sscanf(line, "%s %i\n", reg, &val); if (n < 1 || n > 2) { fprintf(stderr, "?\n"); return; } if (strcasecmp(reg, "CMD") == 0) { off = HERMES_CMD; } else if (strcasecmp(reg, "PARAM0") == 0) { off = HERMES_PARAM0; } else if (strcasecmp(reg, "PARAM1") == 0) { off = HERMES_PARAM1; } else if (strcasecmp(reg, "PARAM2") == 0) { off = HERMES_PARAM2; } else if (strcasecmp(reg, "STATUS") == 0) { off = HERMES_STATUS; } else if (strcasecmp(reg, "RESP0") == 0) { off = HERMES_RESP0; } else if (strcasecmp(reg, "RESP1") == 0) { off = HERMES_RESP1; } else if (strcasecmp(reg, "RESP2") == 0) { off = HERMES_RESP2; } else if (strcasecmp(reg, "INFOFID") == 0) { off = HERMES_INFOFID; } else if (strcasecmp(reg, "RXFID") == 0) { off = HERMES_RXFID; } else if (strcasecmp(reg, "ALLOCFID") == 0) { off = HERMES_ALLOCFID; } else if (strcasecmp(reg, "TXCOMPLFID") == 0) { off = HERMES_TXCOMPLFID; } else if (strcasecmp(reg, "SELECT0") == 0) { off = HERMES_SELECT0; } else if (strcasecmp(reg, "OFFSET0") == 0) { off = HERMES_OFFSET0; } else if (strcasecmp(reg, "DATA0") == 0) { off = HERMES_DATA0; } else if (strcasecmp(reg, "SELECT1") == 0) { off = HERMES_SELECT1; } else if (strcasecmp(reg, "OFFSET1") == 0) { off = HERMES_OFFSET1; } else if (strcasecmp(reg, "DATA1") == 0) { off = HERMES_DATA1; } else if (strcasecmp(reg, "EVSTAT") == 0) { off = HERMES_EVSTAT; } else if (strcasecmp(reg, "INTEN") == 0) { off = HERMES_INTEN; } else if (strcasecmp(reg, "EVACK") == 0) { off = HERMES_EVACK; } else if (strcasecmp(reg, "CONTROL") == 0) { off = HERMES_CONTROL; } else if (strcasecmp(reg, "SWSUPPORT0") == 0) { off = HERMES_SWSUPPORT0; } else if (strcasecmp(reg, "SWSUPPORT1") == 0) { off = HERMES_SWSUPPORT1; } else if (strcasecmp(reg, "SWSUPPORT2") == 0) { off = HERMES_SWSUPPORT2; } else if (strcasecmp(reg, "AUXPAGE") == 0) { off = HERMES_AUXPAGE; } else if (strcasecmp(reg, "AUXOFFSET") == 0) { off = HERMES_AUXOFFSET; } else if (strcasecmp(reg, "AUXDATA") == 0) { off = HERMES_AUXDATA; } else if (strcasecmp(reg, ".") == 0) { display(base); return; } else if (strcasecmp(reg, ",") == 0) { if (n != 2) { fprintf(stderr, "? No FID given\n"); return; } show_record(base, val); return; } else { fprintf(stderr, "? Unknown register\"%s\"\n", reg); return; } if (n == 2) { printf("0x%04x -> 0x%04x\n", val, (int)base+off); outw(val, base+off); } printf("%s (0x%04x) = 0x%04x\n", reg, off, inw(base+off));}intmain(int argc, char *argv[]){ char *e; unsigned long base; int err; char * line; if (argc < 2) usage(); base = strtol(argv[1], &e, 0); if (*e) usage(); err = ioperm(base, 0x40, 1); if (err != 0) fatal("ioperm"); if (argc > 2) { show_records(base); exit(0); } while (1) { line = rl_gets(); if (! line) break; do_line(base, line); free(line); }; exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -