From: a0220410 Date: Mon, 26 Dec 2016 10:55:10 +0000 (+0800) Subject: update rccd2 for end-system integraton X-Git-Url: https://git.ti.com/gitweb?p=tas2555sw-android%2Ftas2555-util-stereo.git;a=commitdiff_plain update rccd2 for end-system integraton --- diff --git a/rccd2/Android.mk b/rccd2/Android.mk new file mode 100755 index 0000000..a22bf18 --- /dev/null +++ b/rccd2/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_C_INCLUDES:= external/rccd2/include +LOCAL_CFLAGS := -O2 -g -W -Wall -D_LARGEFILE_SOURCE -DAIC3XXX_CFW_HOST_BLD -D_FILE_OFFSET_BITS=64 +LOCAL_SRC_FILES:= rccd2.c android_utils.c utils.c +LOCAL_MODULE := rccd2 +LOCAL_STATIC_LIBRARIES:= libcutils libutils liblog +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Werror + +include $(BUILD_EXECUTABLE) diff --git a/rccd2/Makefile b/rccd2/Makefile new file mode 100755 index 0000000..5ba9dce --- /dev/null +++ b/rccd2/Makefile @@ -0,0 +1,57 @@ +ROOT_PATH = ../.. +BUILD := android +#include ../../common/make.config + +RCCD_PORT = 1025 + +NDK_PLATFORM_VER := 9 +APP_PLATFORM := android-16 + +ADB = adb + +ACX_OBJS = acxrun.$(O) android_utils.$(O) $(C_DIR)/utils.$(O) $(H_DIR)/acx_compile.$(O) \ + $(H_DIR)/acx_parser.tab.$(O) $(H_DIR)/lex.yy.$(O) \ + $(H_DIR)/organize_cmds.$(O) $(H_DIR)/lex.cfg.$(O) \ + $(H_DIR)/read_cfg.tab.$(O) $(T_DIR)/host_compile.$(O) + + +RCCD2_OBJS = rccd2.o android_utils.o $(C_DIR)/utils.o + +all: rccd2 acxrun + +rccd2$(EXE_EXT): $(RCCD2_OBJS) + $(CC) $(CFLAGS) $(RCCD2_OBJS) -o $@ $(LFLAGS) + cp rccd2 ../../out/rccd2 + cp rccd2 ../../devout/rccd2 + +acxrun$(EXE_EXT): $(ACX_OBJS) + $(CC) $(CFLAGS) $(ACX_OBJS) -o $@ $(LFLAGS) + +push: rccd2 force + $(ADB) push rccd2 /data + +shell: force + $(ADB) shell + +rccd: push force + $(ADB) shell svc power stayon true + $(ADB) forward tcp:$(RCCD_PORT) tcp:$(RCCD_PORT) + $(ADB) shell /data/rccd2 -v 10 -p $(RCCD_PORT) + +clean: + rm -f $(RCCD2_OBJS) rccd2 acxrun $(ACX_OBJS) + $(MAKE) -C $(H_DIR)/.. clean + +$(H_DIR)/organize_cmds.$(O): $(H_DIR)/init_cram.h + +$(H_DIR)/init_cram.h: force + $(MAKE) BUILD=$(BUILD) -C $(H_DIR)/.. $(patsubst ../%, %, $@) + +$(H_DIR)/%.$(O): force + $(MAKE) BUILD=$(BUILD) -C $(H_DIR)/.. $(patsubst ../%, %, $@) + +$(T_DIR)/%.$(O): force + $(MAKE) BUILD=$(BUILD) -C $(H_DIR)/.. $(patsubst ../%, %, $@) + +force: + @true diff --git a/rccd2/android_utils.c b/rccd2/android_utils.c new file mode 100755 index 0000000..56b091e --- /dev/null +++ b/rccd2/android_utils.c @@ -0,0 +1,526 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include +#include +#include + +#include "aic3xxx_cfw.h" +#include "utils.h" +#include "host_compile.h" +#include "android_utils.h" + +int dump_cmds = 0; +int mode = mode_undef; + +static int dev_fd, dev_no, modern; + +#define DEVICE_ID 98 + +int regDumpId; +char regBuffer[512]; + +//static char *device; +void diag(int lvl, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); +#ifdef ANDROID + __android_log_vprint(lvl, PROGRAM, fmt, ap); +#endif + va_end(ap); + if (getppid() != 1 && (lvl >= (ANDROID_LOG_ERROR - verbose))) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + } + if (lvl >= ANDROID_LOG_FATAL) + exit(1); +} + +const struct { char *node; int cfwb; } devices[] = { + { "aic3xxx_cfw", 1 }, + { "tiload", 0 }, + { "tiload_node", 0 } +}; +int open_device(char *device) +{ + char dfile[64]; + struct stat sbuf; + int i = 0, fd; + if (device) { + // Possible use on host + DBGW("Device not null"); + if (stat(device, &sbuf) == 0) { + strncpy(dfile, device, sizeof(dfile)-1); + goto open; + } + DBGW("Could not locate device \"%s\"", device); + // Switch exclusive to old style device if one is specified (rccd backwards-compatibilty) + while (devices[i].cfwb) + ++i; + } + for (; i < ARRAY_LEN(devices); ++i) { + sprintf(dfile, "/dev/%s", devices[i].node); + if (stat(dfile, &sbuf) == 0) + goto open; + DBGW("Missing device node \"%s\"\n\tLooking for %s in /proc/devices...", dfile, devices[i].node); + FILE *fp = fopen("/proc/devices", "r"); + if (!fp) + DBGF("Unable to read /proc/devices"); + char ln[4096]; + while (fgets(ln, sizeof(ln), fp)) { + if (!strstr(ln, devices[i].node)) + continue; + ln[strlen(ln) - 1] = 0; + DBGW("Found node entry \"%s\"", ln); + int major = strtol(ln, NULL, 10); + DBGW("\tMajor number = %d", major); + if (mknod(dfile, S_IFCHR | 0777, MKDEV(major, 0)) < 0) + DBGF("Unable to\n\tmknod \"%s\" c %d 0", dfile, major); + goto open; + } + } + //This was DBGF + DBGW("Unable find entry for codec diagnostic device. Please check\n" + "\tcat /proc/devices"); + + + // CUstom code + //dfile = "/sdcard/RCCD2/Test.dev"; + sprintf(dfile, "/sdcard/RCCD2/Test.dev"); + i = 4; + DBGW("Device open is redirected to a file now - /sdcard/RCCD2/Test.dev"); + goto open; + + + return -1; +open: + if ((fd = open(dfile, O_RDWR, 0)) < 0) + DBGF("Unable to open device %s", dfile); + modern = devices[i].cfwb; + if (!modern) { + // This stuff below is needed on the old tiload device + // for purposes I don't fully understand + char magic[4]; + ioctl(fd, _IOR(0xE0, 3, int), magic); + } + dev_fd = fd; + dev_no = i; + if (mode == mode_undef) + mode = devices[i].cfwb ? mode_kernel : mode_user; + DBG("Opened device %s, mode:%s", dfile, modern ? "modern" : "legacy"); + return fd; +} + +static int cbook = -1, cpage = -1, lock = 0; + + +static void mread_reg(union cfw_register reg, u8 *buf, int n) +{ + int ncmds = CFW_CMD_BURST_LEN(n); + int err, sz = CFW_BLOCK_SIZE(ncmds); + struct cfw_block *blk = ALLOC(sz); + blk->ncmds = ncmds; + blk->cmd[0].bhdr.cid = CFW_CMD_RBURST; + blk->cmd[0].bhdr.len = n; + blk->cmd[1].reg = reg; + if ((err = read(dev_fd, blk, sz)) != sz) + DBGF("Device read error %d", err); + memcpy(buf, blk->cmd[1].burst.data, n); +} + +static void mwrite_reg(union cfw_register reg, const u8 *buf, int n) +{ + int ncmds = (n <= 3) ? n : CFW_CMD_BURST_LEN(n); + int i, err, sz = CFW_BLOCK_SIZE(ncmds); + struct cfw_block *blk = ALLOC(sz); + blk->ncmds = ncmds; + if (n <= 3) { + for (i = 0; i < n; ++i) { + blk->cmd[i].reg = reg; + blk->cmd[i].reg.offset = reg.offset + i; + blk->cmd[i].reg.data = buf[i + 1]; + } + } + else { + blk->cmd[0].bhdr.cid = CFW_CMD_BURST; + blk->cmd[0].bhdr.len = n; + blk->cmd[1].reg = reg; + memcpy(blk->cmd[1].burst.data, buf + 1, n); + } + if ((err = write(dev_fd, blk, sz)) != sz) + DBGF("Device write error %d", err); +} + + +#define DREAD(reg, b, n) do { \ + int err_ret__; \ + DBGI("r 0x%02x 0x%02x, modern:%d", (b)[0], (n), modern); \ + sprintf(regBuffer, "\nr %d %02x %02x%c", DEVICE_ID, (b)[0], (n),'\0'); \ + write(regDumpId, ®Buffer, strlen(regBuffer)); \ +if (modern) {\ + mread_reg(reg, (b), n); \ +}else if ((err_ret__ = read(dev_fd, b, n)) != n) \ + DBGF("Device read error %d", err_ret__); \ +} while (0) +#define DWRITE(reg, b, n) do { \ + int err_ret__, i__; \ + DBGI("w 0x%02x 0x%02x", (b)[0], (b)[1]); \ + sprintf(regBuffer, "\nw %d %02x %02x%c", DEVICE_ID, (b)[0], (b)[1], '\0'); \ + write(regDumpId, ®Buffer, strlen(regBuffer)); \ +for (i__ = 2; i__ < n; ++i__) \ +{DBGI("> 0x%02x", (b)[i__]); \ + sprintf(regBuffer, " %02x%c", (b)[i__],'\0'); \ + write(regDumpId, ®Buffer, strlen(regBuffer)); }\ +if (modern) {\ + mwrite_reg(reg, b, n); \ +}else if ((err_ret__ = write(dev_fd, b, n)) != n) \ + DBGF("Device write error %d", err_ret__); \ +} while (0) + +static void cfw_lock(int l) +{ + if (l && !lock) { + // FIXME dummy + lock = 1; + } + else if (!l && lock) { + lock = 0; + } +} +static int restore_lock; +static void setpb(union cfw_register r) +{ + DBG("Enter setpb"); + u8 data[2]; + restore_lock = lock; + cfw_lock(1); + DBG("Set Page/Book: (0x%02x,0x%02x)", r.book, r.page); + // if (cbook != r.book) { + if (1){ + //if (cpage != 0) { + if (1){ + data[0] = data[1] = 0; + if (!modern) + DWRITE(r, data, 2); + cpage = 0; + } + data[0] = 0x7F; data[1] = r.book; + if (!modern) + DWRITE(r, data, 2); + cbook = r.book; + DBG("Set Book: [0x%02x]", r.book); + } + + //if (cpage != r.page) { + if (1){ + data[0] = 0; data[1] = r.page; + if (!modern) + DWRITE(r, data, 2); + cpage = r.page; + DBG("Set Page: [0x%02x]", r.page); + } + DBG("Exit setpb"); +} +static void unsetpb(void) +{ + DBG("Enter unsetpb"); + cfw_lock(restore_lock); + DBG("Exit unsetpb"); +} + +static u8 reg_read(union cfw_register reg) +{ + u8 ret; + ret = reg.offset; + setpb(reg); + mread_reg(reg, &ret, 1); + + DREAD(reg, &ret, 1); + unsetpb(); + return ret; +} +static void reg_write(union cfw_register reg) +{ + u8 data[2]; + data[0] = reg.offset; + data[1] = reg.data; + setpb(reg); + DWRITE(reg, data, 2); + unsetpb(); +} +static void reg_wait(union cfw_register reg, u8 mask, u8 data) +{ + u8 cur = reg_read(reg); + while ((cur & mask) != data) { + usleep(2000); + cur = reg_read(reg); + } +} +static int set_bits(u8 *data, u8 mask, u8 val) +{ + u8 nd; + nd = ((*data&(~mask)) | (mask&val)); + if (nd == *data) + return 0; + *data = nd; + return 1; +} +static void cfw_op(unsigned char *var, struct cfw_cmd_op cmd) +{ + u32 op1, op2; + u32 cid = cmd.cid; + + op1 = cmd.op1; + op2 = cmd.op2; + if (cid&CFW_CMD_OP1_ID) + op1 = var[op1]; + if (cid&CFW_CMD_OP2_ID) + op2 = var[op2]; + cid &= ~(CFW_CMD_OP1_ID | CFW_CMD_OP2_ID); + + switch (cid) { + case CFW_CMD_OP_ADD: var[cmd.dst] = op1 + op2; break; + case CFW_CMD_OP_SUB: var[cmd.dst] = op1 - op2; break; + case CFW_CMD_OP_MUL: var[cmd.dst] = op1*op2; break; + case CFW_CMD_OP_DIV: var[cmd.dst] = op1 / op2; break; + case CFW_CMD_OP_AND: var[cmd.dst] = op1 & op2; break; + case CFW_CMD_OP_OR: var[cmd.dst] = op1 | op2; break; + case CFW_CMD_OP_SHL: var[cmd.dst] = (op1 << op2); break; + case CFW_CMD_OP_SHR: var[cmd.dst] = (op1 >> op2); break; + case CFW_CMD_OP_RR: + while (op2--) { + var[cmd.dst] = (op1 >> 1) | ((op1 & 1) << 7); + } + break; + case CFW_CMD_OP_XOR: var[cmd.dst] = op1 ^ op2; break; + case CFW_CMD_OP_NOT: var[cmd.dst] = ~op1; break; + case CFW_CMD_OP_LNOT: var[cmd.dst] = !op1; break; + default: break; + } +} + +static int bulk_write(union cfw_register reg, int count, const u8 *buf) +{ + setpb(reg); + DWRITE(reg, buf - 1, count + 1); + unsetpb(); + return 0; +} + +static int bulk_read(union cfw_register reg, int count, u8 *buf) +{ + int i; + if (reg.offset != buf[-1]) { + DBGW("Mismatched register offset for read (%d != %d)", + reg.offset, buf[-1]); + } + buf[0] = reg.offset; + + if (reg.offset == 0xFF && reg.book == 0xFF && reg.page == 0xFF) + { + /* To handle Ping*/ + buf[0] = 0x7c; + buf[1] = 00; + buf[2] = 01; + buf[3] = 02; + + DBGI("..........PING......."); + + } + else + { + + setpb(reg); + //DBG("Commenting of DRED"); + DREAD(reg, buf, count); + unsetpb(); + } + DBGI("Reading from (%d,%d,%d)... %d bytes", reg.book, reg.page, reg.offset, + count); + for (i = 0; i < count; i += 8) { + switch (count - i) { + case 1: DBGI("# 0x%02x", buf[i + 0]); break; + case 2: DBGI("# 0x%02x 0x%02x", buf[i + 0], buf[i + 1]); break; + case 3: DBGI("# 0x%02x 0x%02x 0x%02x", buf[i + 0], buf[i + 1], buf[i + 2]); break; + case 4: DBGI("# 0x%02x 0x%02x 0x%02x 0x%02x", buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3]); break; + case 5: DBGI("# 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4]); break; + case 6: DBGI("# 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5]); break; + case 7: DBGI("# 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6]); break; + default:DBGI("# 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]); break; + } + } + + + return 0; +} + +static void run_block_slow(struct cfw_block *pb, u8 *var) +{ + int pc = 0; + int cond = 0; + u8 data; +// int i; + + DBG("%s: pb->ncmds=%d", __FUNCTION__, pb->ncmds); + while (pc < pb->ncmds) { + union cfw_cmd *c = &(pb->cmd[pc]); + if (c->cid != CFW_CMD_BRANCH_IM && + c->cid != CFW_CMD_BRANCH_ID && + c->cid != CFW_CMD_NOP) + cond = 0; + DBGI("%s: Case No %d:", __FUNCTION__, c->cid); + switch (c->cid) { + + case 0 ... (CFW_CMD_NOP - 1) : + DBGI("CFW_CMD_NOP-1"); + reg_write(c->reg); + pc += 1; + break; + case CFW_CMD_NOP: + DBGI("CFW_CMD_NOP"); + pc += 1; + break; + case CFW_CMD_DELAY: + DBGI("CFW_CMD_DELAY"); + usleep(c->delay.delay * 1000 + c->delay.delay_fine * 4); + pc += 1; + break; + case CFW_CMD_UPDTBITS: + DBGI("CFW_CMD_UPDTBITS"); + c[1].reg.data = reg_read(c[1].reg); + set_bits(&data, c->bitop.mask, c[1].reg.data); + reg_write(c[1].reg); + pc += 2; + break; + case CFW_CMD_WAITBITS: + DBGI("CFW_CMD_WAITBITS"); + reg_wait(c[1].reg, c->bitop.mask, c[1].reg.data); + pc += 2; + break; + case CFW_CMD_LOCK: + DBGI("CFW_CMD_LOCK"); + cfw_lock(c->lock.lock); + pc += 1; + break; + case CFW_CMD_BURST: + DBGI("CFW_CMD_BURST"); + bulk_write(c[1].reg, c->bhdr.len, + c[1].burst.data); + pc += CFW_CMD_BURST_LEN(c->bhdr.len); + break; + case CFW_CMD_RBURST: + DBGI("CFW_CMD_RBURST"); + bulk_read(c[1].reg, c->bhdr.len, + c[1].burst.data); + pc += CFW_CMD_BURST_LEN(c->bhdr.len); + break; + case CFW_CMD_LOAD_VAR_IM: + set_bits(&var[c->ldst.dvar], + c->ldst.mask, c->ldst.svar); + pc += 1; + break; + case CFW_CMD_LOAD_VAR_ID: + if (c->ldst.svar != c->ldst.dvar) { + set_bits(&var[c->ldst.dvar], + c->ldst.mask, var[c->ldst.svar]); + pc += 1; + } + else { + data = reg_read(c[1].reg); + set_bits(&var[c->ldst.dvar], + c->ldst.mask, data); + pc += 2; + } + break; + case CFW_CMD_STORE_VAR: + if (c->ldst.svar != c->ldst.dvar) { + c[1].reg.data = reg_read(c[1].reg); + set_bits(&(c[1].reg.data), + var[c->ldst.dvar], + var[c->ldst.svar]); + reg_write(c[1].reg); + } + else { + c[1].reg.data = reg_read(c[1].reg); + set_bits(&data, c->ldst.mask, + var[c->ldst.svar]); + reg_write(c[1].reg); + } + pc += 2; + break; + case CFW_CMD_COND: + cond = var[c->cond.svar] & c->cond.mask; + pc += 1; + break; + case CFW_CMD_BRANCH: + pc = c->branch.address; + break; + case CFW_CMD_BRANCH_IM: + if (c->branch.match == cond) + pc = c->branch.address; + else + pc += 1; + break; + case CFW_CMD_BRANCH_ID: + if (var[c->branch.match] == cond) + pc = c->branch.address; + else + pc += 1; + break; + case CFW_CMD_PRINT: + { + union cfw_cmd *parglist = c + CFW_CMD_PRINT_ARG(c->print); +#ifdef ANDROID + DBGI(c->print.fmt, + var[parglist->print_arg[0]], + var[parglist->print_arg[1]], + var[parglist->print_arg[2]], + var[parglist->print_arg[3]]); +#else + printf(c->print.fmt, + var[parglist->print_arg[0]], + var[parglist->print_arg[1]], + var[parglist->print_arg[2]], + var[parglist->print_arg[3]]); +#endif + pc += CFW_CMD_PRINT_LEN(c->print); + } + break; + case CFW_CMD_OP_START ... CFW_CMD_OP_END: + cfw_op(var, c->op); + pc += 1; + break; + default: + DBGW("Unknown cmd command %x. Skipped", c->cid); + pc += 1; + break; + } + } + +} + +void run_block(struct cfw_block *pb, u8 *var) +{ + char *filePath = "/sdcard/RCCD2/regDump.txt"; + if (!modern || (mode != mode_kernel)) { + DBGI("Calling run block slow"); + regDumpId = open(filePath, O_RDWR | O_APPEND | O_CREAT, 0644); + run_block_slow(pb, var); + close(regDumpId); + return; + } + int r, n = CFW_BLOCK_SIZE(pb->ncmds); + DBGI("Calling write, ncmds %d, len %d, %x, size of union cfw_cmd %d ", n, CFW_BLOCK_SIZE(pb->ncmds - 1), pb->cmd[0].reg.data, sizeof(union cfw_cmd)); + if ((r = write(dev_fd, pb, n)) != n) + DBGF("Device write error %d", r); + +} diff --git a/rccd2/include/aic3xxx_cfw.h b/rccd2/include/aic3xxx_cfw.h new file mode 100755 index 0000000..09922d9 --- /dev/null +++ b/rccd2/include/aic3xxx_cfw.h @@ -0,0 +1,498 @@ +/** +* \file Codec Firmware Declarations +*/ +#ifndef CFW_FIRMWARE_H_ +#define CFW_FIRMWARE_H_ + +/** \defgroup bt Basic Types */ +/* @{ */ +#ifndef AIC3XXX_CFW_HOST_BLD +#include +#else +//typedef unsigned char u8; +//typedef unsigned short int u16; +//typedef unsigned long int u32; +//typedef unsigned int u32; +#endif +//typedef signed char i8; +//typedef signed short int i16; +//typedef signed long int i32; + +#define CFW_FW_MAGIC 0xC0D1F1ED +/** \defgroup pd Arbitrary Limitations */ +/* @{ */ +#ifndef CFW_MAX_ID +# define CFW_MAX_ID (64) /**= CFW_CMD_DELAY) +/** +* CFW Block Type +* +* Block identifier +* +*/ +enum __attribute__((__packed__)) cfw_block_t{ + CFW_BLOCK_SYSTEM_PRE, + CFW_BLOCK_A_INST, + CFW_BLOCK_A_A_COEF, + CFW_BLOCK_A_B_COEF, + CFW_BLOCK_A_F_COEF, + CFW_BLOCK_D_INST, + CFW_BLOCK_D_A1_COEF, + CFW_BLOCK_D_B1_COEF, + CFW_BLOCK_D_A2_COEF, + CFW_BLOCK_D_B2_COEF, + CFW_BLOCK_D_F_COEF, + CFW_BLOCK_SYSTEM_POST, + CFW_BLOCK_N, + CFW_BLOCK_INVALID, +}; +#define CFW_BLOCK_D_A_COEF CFW_BLOCK_D_A1_COEF +#define CFW_BLOCK_D_B_COEF CFW_BLOCK_D_B1_COEF + +/** + * CFW Register + * + * A single reg write + * + */ +union aic_register { + struct { + u8 book; + u8 page; + u8 offset; + u8 data; + }; + u32 bpod; +}; + +/** +* CFW Block +* +* A block of logically grouped sequences/commands/cmd-commands +* +*/ +struct cfw_block { + u8 type; + //enum cfw_block_t type; + int ncmds; + union cfw_cmd cmd[]; +}; +#define CFW_BLOCK_SIZE(ncmds) (sizeof(struct cfw_block) + \ + ((ncmds)*sizeof(union cfw_cmd))) +/** +* CFW Image +* +* A downloadable image +*/ +struct cfw_image { + char name[CFW_MAX_ID]; /**< Name of the pfw/overlay/configuration*/ + char *desc; /**< User string*/ + int mute_flags; + struct cfw_block *block[CFW_BLOCK_N]; +}; +/** +* CFW PLL +* +* PLL configuration sequence and match critirea +*/ +struct cfw_pll { + char name[CFW_MAX_ID]; /**< Name of the PLL sequence*/ + char *desc; /**< User string*/ + struct cfw_block *seq; +}; +/** +* CFW Control +* +* Run-time control for a process flow +*/ +struct cfw_control { + char name[CFW_MAX_ID]; /**< Control identifier*/ + char *desc; /**< User string*/ + int mute_flags; + int min; /**< Min value of control (*100)*/ + int max; /**< Max value of control (*100)*/ + int step; /**< Control step size (*100)*/ + int imax; /**< Max index into controls array*/ + int ireset; /**< Reset control to defaults*/ + int icur; /**< Last value set*/ + struct cfw_block **output; /**< Array of sequences to send*/ +}; +/** +* Process flow +* +* Complete description of a process flow +*/ +struct cfw_pfw { + char name[CFW_MAX_ID]; /**< Name of the process flow*/ + char *desc; /**< User string*/ + u32 version; + u8 prb_a; + u8 prb_d; + int novly; /**< Number of overlays (1 or more)*/ + int ncfg; /**< Number of configurations (0 or more)*/ + int nctrl; /**< Number of run-time controls*/ + struct cfw_image *base; /**< Base sequence*/ + struct cfw_image **ovly_cfg; /**< Overlay and cfg*/ + /**< patches (if any)*/ + struct cfw_control **ctrl; /**< Array of run-time controls*/ +}; +#define CFW_OCFG_NDX(p, o, c) (((o)*(p)->ncfg)+(c)) +/** +* Process transition +* +* Sequence for specific state transisitions within the driver +* +*/ +struct cfw_transition { + char name[CFW_MAX_ID]; /**< Name of the transition*/ + char *desc; /**< User string*/ + struct cfw_block *block; +}; +/** +* Device audio mode +* +* Link operating modes to process flows, +* configurations and sequences +* +*/ +struct cfw_mode { + char name[CFW_MAX_ID]; + char *desc; /**< User string*/ + u32 flags; + u8 pfw; + u8 ovly; + u8 cfg; + u8 pll; + struct cfw_block *entry; + struct cfw_block *exit; +}; +struct cfw_asoc_toc_entry { + char etext[CFW_MAX_ID]; + int mode; + int cfg; +}; +struct cfw_asoc_toc { + int nentries; + struct cfw_asoc_toc_entry entry[]; +}; +/** +* CFW Project +* +* Top level structure describing the CFW project +*/ +struct cfw_project { + u32 magic; /**< magic number for identifying F/W file*/ + u32 if_id; /**< Interface match code */ + u32 size; /**< Total size of the firmware (including this header)*/ + u32 cksum; /**< CRC32 of the pickled firmware */ + u32 version; /**< Firmware version (from CFD file)*/ + u32 tstamp; /**< Time stamp of firmware build (epoch seconds)*/ + char name[CFW_MAX_ID]; /**< Project name*/ + char *desc; /**< User string*/ + enum cfw_dfamily dfamily; /**< Device family*/ + enum cfw_device device; /**< Device identifier*/ + u32 flags; /**< CFW flags*/ + struct cfw_transition **transition; /**< Transition sequences*/ + u16 npll; /**< Number of PLL settings*/ + struct cfw_pll **pll; /**< PLL settings*/ + u16 npfw; /**< Number of process flows*/ + struct cfw_pfw **pfw; /**< Process flows*/ + u16 nmode; /**< Number of operating modes*/ + struct cfw_mode **mode; /**< Modes*/ + struct cfw_asoc_toc *asoc_toc; /**< list of amixer controls*/ +}; +void run_block(struct cfw_block *pb, u8 *var); +/* @} */ +/* **CFW_INTERFACE_ID=0x3FA6D547** */ +#endif /* CFW_FIRMWARE_H_ */ + diff --git a/rccd2/include/android_utils.h b/rccd2/include/android_utils.h new file mode 100755 index 0000000..2ab1e18 --- /dev/null +++ b/rccd2/include/android_utils.h @@ -0,0 +1,55 @@ +#ifndef ANDROID_UTILS_H_ +#define ANDROID_UTILS_H_ + +#include "host_compile.h" + +#ifdef ANDROID +#include +#include +#else + +typedef enum android_LogPriority { + ANDROID_LOG_UNKNOWN = 0, + ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ + ANDROID_LOG_VERBOSE, + ANDROID_LOG_DEBUG, + ANDROID_LOG_INFO, + ANDROID_LOG_WARN, + ANDROID_LOG_ERROR, + ANDROID_LOG_FATAL, + ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ +} android_LogPriority; + +#endif + +/* TAS MACROS */ +#define TAS2560_REG(book,page,reg) (((unsigned int)book * 256 *128) + ((unsigned int)page * 128) + reg) +#define TAS2560_BOOK_ID(reg) ((unsigned char)(reg / (256*128))) +#define TAS2560_PAGE_ID(reg) ((unsigned char)((reg % (256 * 128)) / 128)) +#define TAS2560_REG_ID(reg) ((unsigned char)((reg % (256 * 128)) % 128)) + +int open_device(char *device); +void diag(int lvl, char *fmt, ...); +extern int dump_cmds; +enum { mode_undef, mode_user, mode_kernel }; +extern int mode; + +#ifndef PROGRAM +# define PROGRAM "aic3xxx" +#endif + + +#undef DBG +#undef DBGF + +#define DBGD(fmt, ...) do { \ + if (dump_cmds) \ + LOG(ANDROID_LOG_DEBUG, fmt, ##__VA_ARGS__); \ + } while (0) +#define DBG(fmt, ...) LOG(ANDROID_LOG_DEBUG, "[%s:%d] " fmt, __FILE__, \ + __LINE__, ##__VA_ARGS__) +#define DBGI(fmt, ...) LOG(ANDROID_LOG_INFO, fmt, ##__VA_ARGS__) +#define DBGW(fmt, ...) LOG(ANDROID_LOG_WARN, fmt, ##__VA_ARGS__) +#define DBGF(fmt, ...) LOG(ANDROID_LOG_FATAL, fmt, ##__VA_ARGS__) +#define LOG(lvl, fmt, ...) diag(lvl, fmt, ##__VA_ARGS__) +#endif diff --git a/rccd2/include/host_compile.h b/rccd2/include/host_compile.h new file mode 100755 index 0000000..794a8c3 --- /dev/null +++ b/rccd2/include/host_compile.h @@ -0,0 +1,41 @@ +#ifndef HOST_COMPILE_H_ +#define HOST_COMPILE_H_ + +#define printk warn +#define MODULE_DESCRIPTION(x) +#define MODULE_LICENSE(x) +#define MODULE_AUTHOR(x) + +//#include +typedef unsigned char u8; +typedef unsigned short int u16; +//typedef unsigned long int u32; +typedef unsigned int u32; +typedef signed char i8; +typedef signed short int i16; +typedef signed long int i32; +//#define crc32 aic_crc32 +struct aic_firmware *aic_unpickle(void *pcfw, int n); +unsigned int crc32_local(unsigned int *pdata, int n); +#if 0 +static inline unsigned int crc32(unsigned int seed, unsigned int *pdata, int n) +{ + return crc32_local(pdata, n); +} +#endif +# define _GNU_SOURCE +# include +# include "utils.h" +# include +# include +#ifndef EINVAL +# define EINVAL 1 +#endif + +// Hack, Hack +#ifndef AIC3XX_COPS_MDSP_D +#define AIC3XX_COPS_MDSP_D (0x00000003u) +#define AIC3XX_COPS_MDSP_A (0x00000030u) +#endif + +#endif diff --git a/rccd2/include/rccd2.h b/rccd2/include/rccd2.h new file mode 100755 index 0000000..f26aa71 --- /dev/null +++ b/rccd2/include/rccd2.h @@ -0,0 +1,62 @@ +#ifndef RCCD2_H_ +#define RCCD2_H_ + +#define FW_ID_ADDRESS 0x1FBC + +#define TARGET_I2C 5 +#define RCCD_MAGIC "TICC" +#define RCCD_PING "PING" +#define DEFAULT_FWID "FWIDTLV320AIC3262EVM-U" +#define RCCD_MAX_PACKET (32*1024) +#define RCCD_MAX_STREAMS (8) + +enum __attribute__ ((__packed__)) rccd_cmd_id { + RCCD_CMD_WRITE = 0x02, + RCCD_CMD_READ = 0x03, + RCCD_CMD_FWID = 0x05, + RCCD_CMD_SLAVE = 0x06, + + RCCD_CMD_BLOCK = 0x80, + RCCD_CMD_OPEN, + RCCD_CMD_CLOSE, + RCCD_CMD_PLAY, + RCCD_CMD_CAPTURE, + RCCD_CMD_START, + RCCD_CMD_STOP, + RCCD_CMD_MGET, + RCCD_CMD_MSET, + RCCD_CMD_NCTLS, + RCCD_CMD_CTL +}; + +struct rccd_cmd { + u8 len; + enum rccd_cmd_id cid; + u8 options; + u8 data[]; +}; +struct rccd_cmd_alsa { + u8 len; + enum rccd_cmd_id cid; + u8 stream; + u8 device; + unsigned int flags; + unsigned int buffer_size; + unsigned int channels; + unsigned int rate; + unsigned int period_size; + unsigned int period_count; + unsigned int format; + u8 data[]; +}; + +struct rccd_request { + u8 magic[4]; + u8 len; + u8 app; + u8 target; + u8 result; + struct rccd_cmd cmd[]; +}; + +#endif diff --git a/rccd2/include/utils.h b/rccd2/include/utils.h new file mode 100755 index 0000000..486d77b --- /dev/null +++ b/rccd2/include/utils.h @@ -0,0 +1,68 @@ +#ifndef UTILS_H_ +#define UTILS_H_ + +#include +#include + +#include "host_compile.h" + +extern int verbose; +void error(char *fmt, ...); +void warn(char *fmt, ...); +void dbg(const char *f, int ln, char *fmt, ...); + +#define warn_once(f, ...) do { \ + static int prn_out__ = 0; \ + if (!prn_out__) { \ + warn(f, ##__VA_ARGS__); \ + prn_out__ = 1; \ + } \ + } while (0) + + +#define DBG(f, ...) dbg(__FILE__, __LINE__, f, ##__VA_ARGS__) +#define DBGF(f, ...) dbg(__FUNCTION__, __LINE__, f, ##__VA_ARGS__) + +#define ARRAY_LEN(x) ((int)(sizeof(x)/sizeof((x)[0]))) +#define MAX2(x, y)(((x)>(y))?(x):(y)) +#define MIN2(x, y)(((x)<(y))?(x):(y)) + + +#ifdef WIN32 +char *strcasestr(const char *haystack, const char *needle); +#endif + +#define ALLOC(x) safe_alloc(__FUNCTION__, __FILE__, __LINE__, x) +#define REALLOC(x, n) do { \ + (x) = realloc((x), n); \ + if (!(x)) { \ + error("out of memory: request for %d bytes in %s() [%s:%d]", \ + n, __FUNCTION__, __FILE__, __LINE__); \ + } \ + } while (0) + +void *safe_alloc(const char *fn, const char *file, int ln, int n); +void safe_snprintf(char *str, size_t size, const char *format, ...); + +int flt2fix(char *s); +void *slurp(const char *f, int *np); + +char *make_opts(const struct option *opts); +char *change_extn(const char *fname, char *ext); +char *get_extn(const char *fname); +double clkspec(const char *mclk); + +void add_path(char *path); +FILE *loc_and_open(char *file); +int file_exists(const char *path); + +int split(const char *s, char ***flds); +void free_flds(char **flds, int n); + + +#ifndef __ARMEL__ +// No regexp library installed for Linux/Android +//int grok_reg_spec(const char *exp, union aic_register *r); +#endif + +#endif diff --git a/rccd2/rccd2.bat b/rccd2/rccd2.bat new file mode 100755 index 0000000..d87a3dc --- /dev/null +++ b/rccd2/rccd2.bat @@ -0,0 +1,141 @@ +@ECHO OFF +:: Default options +set ADB=adb.exe +set RCCD2=rccd2 +set PORT=80 +set SAFE= +set CARD=0 +set LOGCAT=OFF +set DEBUG=OFF + +goto GETOPTS + +:USAGE +echo. +echo. rccd2.bat -- Start RCCD server on target Android phone +echo. +echo. Usage: rccd2 [/help] [/safe] [/supersafe] [/card:N] [/port:N] +echo. [/adb:ADB] [/rccd2:RCCD2] [/logcat] +echo. +echo. Options: +echo. +echo. /help Display this help text and exit +echo. /port:N Set port number to N (Default: %PORT%) +echo. /card:N Select sound card N (Default: %CARD%) +echo. /adb:ADB Use ADB as the adb executable +echo. (Default: %ADB%) +echo. /rccd2:RCCD2 Use RCCD2 as the target rccd2 executable +echo. (Default: %RCCD2%) +echo. /logcat Start adb logcat at the end +echo. /debug Output debug information +echo. +goto END + + +:GETOPTS + set SWITCHOPT=%1 + if [%SWITCHOPT%] == [] goto START + + for /F "tokens=1,2 delims=: " %%a IN ("%SWITCHOPT%") DO SET SWITCH=%%a&set VALUE=%%b + + shift + + if [%SWITCH%] == [/h] goto USAGE + if [%SWITCH%] == [/H] goto USAGE + if [%SWITCH%] == [/?] goto USAGE + if [%SWITCH%] == [/help] goto USAGE + if [%SWITCH%] == [/HELP] goto USAGE + + if [%SWITCH%] == [/safe] goto SET_SAFE_ON + if [%SWITCH%] == [/SAFE] goto SET_SAFE_ON + if [%SWITCH%] == [/supersafe] goto SET_SSAFE_ON + if [%SWITCH%] == [/SUPERSAFE] goto SET_SSAFE_ON + + if [%SWITCH%] == [/card] goto SET_CARD + if [%SWITCH%] == [/CARD] goto SET_CARD + + if [%SWITCH%] == [/port] goto SET_PORT + if [%SWITCH%] == [/PORT] goto SET_PORT + + if [%SWITCH%] == [/adb] goto SET_ADB + if [%SWITCH%] == [/ADB] goto SET_ADB + + if [%SWITCH%] == [/rccd2] goto SET_RCCD2 + if [%SWITCH%] == [/RCCD2] goto SET_RCCD2 + + if [%SWITCH%] == [/logcat] goto SET_LOGCAT_ON + if [%SWITCH%] == [/LOGCAT] goto SET_LOGCAT_ON + + if [%SWITCH%] == [/debug] goto SET_DEBUG_ON + if [%SWITCH%] == [/DEBUG] goto SET_DEBUG_ON + + + echo. Unknown option %SWITCH%. Ignored +goto GETOPTS + + +:SET_SAFE_ON + set SAFE=-s +goto GETOPTS + +:SET_SSAFE_ON + set SAFE=-S +goto GETOPTS + +:SET_PORT + set PORT=%VALUE% +goto GETOPTS + +:SET_CARD + set CARD=%VALUE% +goto GETOPTS + +:SET_ADB + set ADB=%VALUE% +goto GETOPTS + +:SET_RCCD2 + set RCCD2=%VALUE% +goto GETOPTS + +:SET_LOGCAT_ON + set LOGCAT=ON +goto GETOPTS + + +:SET_DEBUG_ON + REM echo ON + set DEBUG=ON +goto GETOPTS + +:START + +if [%DEBUG%] == [OFF] goto RUN + echo. "Starting RCCD..." + echo. SAFE=%SAFE% + echo. PORT=%PORT% + echo. CARD=%CARD% + echo. ADB=%ADB% + echo. RCCD2=%RCCD2% + echo. LOGCAT=%LOGCAT% + +:RUN + +%ADB% root +%ADB% remount +%ADB% shell svc power stayon true +ping localhost > NUL +%ADB% push %RCCD2% /system/bin/rccd2 +%ADB% shell chmod 0777 /system/bin/rccd2 +%ADB% forward tcp:%PORT% tcp:%PORT% +%ADB% shell /system/bin/rccd2 -k +%ADB% shell /system/bin/rccd2 -p %PORT% -r %CARD% %SAFE% + +if [%DEBUG%] == [ON] echo "RCCD2 is running..." + +if [%LOGCAT%] == [OFF] goto END + %ADB% logcat -s aic3xxx + +:END + + diff --git a/rccd2/rccd2.c b/rccd2/rccd2.c new file mode 100755 index 0000000..eb0e3b6 --- /dev/null +++ b/rccd2/rccd2.c @@ -0,0 +1,654 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "android_utils.h" +#include "rccd2.h" +#include "aic3xxx_cfw.h" + +/* Max connection requests */ +#define MAXPENDING (16) +#define BUFFSIZE (256) +#define DEFAULT_PORT (80) + +/* State of each independent connection */ +struct rccd_hdl { + u32 pcounter; + char fwid[32]; + int clientsock; + int fCtrl; + pthread_mutex_t *mutex; + int slave_id,book, page; + u8 buffer[RCCD_MAX_PACKET]; + struct cfw_block block; +}; + +#define CRITICAL(code_section__) do { \ +if (pthread_mutex_lock(pc->mutex)) \ + DBGF("Error obtaining mutex lock"); \ + \ + code_section__; \ + \ +if (pthread_mutex_unlock(pc->mutex)) \ + DBGF("Error releasing mutex lock"); \ +} while (0) + +void legacy_read(struct rccd_hdl *pc, u8 *buf, int n) +{ + pc->block.ncmds = CFW_CMD_BURST_LEN(n); + pc->block.cmd[0].bhdr.cid = CFW_CMD_RBURST; + pc->block.cmd[0].bhdr.len = n; + //pc->block.cmd[1].burst.slave_id = pc->slave_id; + pc->block.cmd[1].burst.book = pc->book; + pc->block.cmd[1].burst.page = pc->page; + pc->block.cmd[1].burst.offset = buf[0]; + DBG("legacy_read: (%d,%d,%d) %d bytes", pc->book, pc->page, buf[0], n); + CRITICAL(run_block(&(pc->block), NULL)); + memcpy(buf + 1, pc->block.cmd[1].burst.data, n); +} + +void legacy_write(struct rccd_hdl *pc, u8 *buf, int n) +{ + u8 *pd = buf; + if (buf[0] == 127) { + pc->book = buf[1]; + if (n != 2) + DBGW("Received book change as part of burst command. " + "Additional writes have been ignored (n=%d)", n); + return; + } + if (buf[0] == 0) { + pc->page = buf[1]; + --n; + if (n <= 1) + return; + ++pd; + pd[0] = 1; + } + pc->block.ncmds = CFW_CMD_BURST_LEN(n - 1); + pc->block.cmd[0].bhdr.cid = CFW_CMD_BURST; + pc->block.cmd[0].bhdr.len = n - 1; + //pc->block.cmd[1].burst.slave_id = pc->slave_id; + pc->block.cmd[1].burst.book = pc->book; + pc->block.cmd[1].burst.page = pc->page; + pc->block.cmd[1].burst.offset = pd[0]; + memcpy(pc->block.cmd[1].burst.data, &pd[1], n - 1); + DBG("legacy_write: (%d,%d,%d) %d bytes", pc->book, pc->page, pd[0], n - 1); + CRITICAL(run_block(&(pc->block), NULL)); +} + +int rccd_cmd(struct rccd_hdl *pc, struct rccd_cmd *cmd, int len) +{ + DBG("Getting into rccd_cmd"); + const char * const cid_str[] = { + [RCCD_CMD_READ] = "RCCD_CMD_READ", + [RCCD_CMD_WRITE] = "RCCD_CMD_WRITE", + [RCCD_CMD_SLAVE] = "RCCD_CMD_SLAVE", + [RCCD_CMD_FWID] = "RCCD_CMD_FWID", + [RCCD_CMD_BLOCK] = "RCCD_CMD_BLOCK", + [RCCD_CMD_OPEN] = "RCCD_CMD_OPEN", + [RCCD_CMD_CLOSE] = "RCCD_CMD_CLOSE", + [RCCD_CMD_PLAY] = "RCCD_CMD_PLAY", + [RCCD_CMD_CAPTURE] = "RCCD_CMD_CAPTURE", + [RCCD_CMD_START] = "RCCD_CMD_START", + [RCCD_CMD_STOP] = "RCCD_CMD_STOP", + [RCCD_CMD_MGET] = "RCCD_CMD_MGET", + [RCCD_CMD_MSET] = "RCCD_CMD_MSET", + [RCCD_CMD_NCTLS] = "RCCD_CMD_NCTLS", + [RCCD_CMD_CTL] = "RCCD_CMD_CTL", + }; + + DBG("%s: cid=%0x \"%s\" len=%d", __FUNCTION__, cmd->cid, cid_str[cmd->cid], + cmd->len); + + //if (!pc->mixer && cmd->cid > RCCD_CMD_BLOCK) + // DBGF("Attempt to do ALSA operation when no sound card is present"); + + switch (cmd->cid) { + case RCCD_CMD_READ: + DBG("rccd:RCCD_CMD_READ"); + if (cmd->len < 4) + break; + legacy_read(pc, cmd->data, cmd->len - 4); + break; + case RCCD_CMD_WRITE: + DBG("rccd:RCCD_CMD_WRITE"); + if (cmd->len < 4) + break; + legacy_write(pc, cmd->data, cmd->len - 4 + 1); + break; + case RCCD_CMD_BLOCK: + { + DBG("rccd:RCCD_CMD_BLOCK"); + u8 var[256]; + struct cfw_block *b = (void *)cmd->data; + len = CFW_BLOCK_SIZE(b->ncmds) + sizeof(struct rccd_cmd); + CRITICAL(run_block(b, var)); + } + break; + case RCCD_CMD_OPEN: + DBG("rccd:RCCD_CMD_OPEN - : NOT SUPPORTED"); + break; + case RCCD_CMD_CLOSE: + DBG("rccd:RCCD_CMD_CLOSE - : NOT SUPPORTED"); + break; + case RCCD_CMD_PLAY: + DBG("rccd:RCCD_CMD_PLAY - : NOT SUPPORTED"); + break; + + case RCCD_CMD_CAPTURE: + DBG("rccd:RCCD_CMD_CAPTURE - : NOT SUPPORTED"); + break; + + case RCCD_CMD_START: + DBG("rccd:RCCD_CMD_START - : NOT SUPPORTED"); + break; + + case RCCD_CMD_STOP: + DBG("rccd:RCCD_CMD_STOP - : NOT SUPPORTED"); + break; + case RCCD_CMD_MGET: + DBG("rccd:RCCD_CMD_MGET - : NOT SUPPORTED"); + break; + + case RCCD_CMD_MSET: + DBG("rccd:RCCD_CMD_MSET - : NOT SUPPORTED"); + break; + + case RCCD_CMD_NCTLS: + DBG("rccd:RCCD_CMD_NCTLS - : NOT SUPPORTED"); + break; + + case RCCD_CMD_CTL: + DBG("rccd:RCCD_CMD_CTL - : NOT SUPPORTED"); + break; + + case RCCD_CMD_FWID: + { + DBG("rccd:RCCD_CMD_FWID"); + //u32 addr = (cmd->data[1] << 8) | (cmd->data[2]); + strcpy((char *)(cmd->data + 3), pc->fwid); + } + break; + case RCCD_CMD_SLAVE: + { + u8 slave = cmd->data[0]; + int client = slave; + ioctl(pc->fCtrl, _IOW(0xE0, 5, int), &client); + DBG("Setting slave : 0x%x", slave); + } + break; + default: + DBGW("HandleI2CCmd: unsupported command: %d", + cmd->cid); + } + DBG("Getting out of rccd_cmd"); + return len; +} + +void dump_pkt(u8 *b, int nLength) +{ + int i; + DBG("Packet[length=%d]", nLength); + for (i = 0; i < nLength; i += 8) { + switch (nLength - i) { + case 1: DBG(" 0x%02x", b[i + 0]); break; + case 2: DBG(" 0x%02x 0x%02x", b[i + 0], b[i + 1]); break; + case 3: DBG(" 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2]); break; + case 4: DBG(" 0x%02x 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2], b[i + 3]); break; + case 5: DBG(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2], b[i + 3], b[i + 4]); break; + case 6: DBG(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2], b[i + 3], b[i + 4], b[i + 5]); break; + case 7: DBG(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2], b[i + 3], b[i + 4], b[i + 5], b[i + 6]); break; + default:DBG(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2], b[i + 3], b[i + 4], b[i + 5], b[i + 6], b[i + 7]); break; + } + } +} + +void write_pkt(u8 *b, int nLength, char *filePath) +{ + int i; + int output_fd, ret_out; + char buffer[512]; + + output_fd = open(filePath, O_RDWR | O_APPEND | O_CREAT, 0644); + + sprintf(buffer, "Packet[length=%d]%c", nLength,'\0'); + ret_out = write(output_fd, &buffer, strlen(buffer)); + for (i = 0; i < nLength; i += 8) { + switch (nLength - i) { + case 1: sprintf(buffer, " 0x%02x%c", b[i + 0],'\0'); break; + case 2: sprintf(buffer, " 0x%02x 0x%02x%c", b[i + 0], b[i + 1],'\0'); break; + case 3: sprintf(buffer, " 0x%02x 0x%02x 0x%02x%c", b[i + 0], b[i + 1], b[i + 2],'\0'); break; + case 4: sprintf(buffer, " 0x%02x 0x%02x 0x%02x 0x%02x%c", b[i + 0], b[i + 1], b[i + 2], b[i + 3],'\0'); break; + case 5: sprintf(buffer, " 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x%c", b[i + 0], b[i + 1], b[i + 2], b[i + 3], b[i + 4],'\0'); break; + case 6: sprintf(buffer, " 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x%c", b[i + 0], b[i + 1], b[i + 2], b[i + 3], b[i + 4], b[i + 5], '\0'); break; + case 7: sprintf(buffer, " 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x%c", b[i + 0], b[i + 1], b[i + 2], b[i + 3], b[i + 4], b[i + 5], b[i + 6], '\0'); break; + default:sprintf(buffer, " 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x%c", b[i + 0], b[i + 1], b[i + 2], b[i + 3], b[i + 4], b[i + 5], b[i + 6], b[i + 7], '\0'); break; + } + ret_out = write(output_fd, &buffer, strlen(buffer)); + } + sprintf(buffer, "\n%c",'\0'); + ret_out = write(output_fd, &buffer, strlen(buffer)); + close(output_fd); +} + +static int get_packet(struct rccd_hdl *pc, u8 *p, int max, int *is_ping) +{ + int ret; + int sock = pc->clientsock; + if ((ret = recv(sock, p, max, 0)) <= 0) + goto err; + struct rccd_request *preq = (void *)p; + ++pc->pcounter; + DBG("[%8d] Received PKT %d bytes", pc->pcounter, ret); + dump_pkt(p, ret); + write_pkt(p, ret, "/sdcard/RCCD2/bytes.txt"); + if (preq->target != TARGET_I2C) + DBGF("Unsupported Target ID: %d\n", preq->target); + if (preq->len < 8) { + DBGW("Packet too short"); + goto err; + } + + DBG("MAGIC %s", preq->magic); + if (!memcmp(preq->magic, RCCD_PING, sizeof(preq->magic))) + { + DBG("PING... "); + *is_ping = 1; + return ret; + } + + if (memcmp(preq->magic, RCCD_MAGIC, sizeof(preq->magic))) { + DBGW("Incorrect signature: %c%c%c%c", preq->magic[0], + preq->magic[1], preq->magic[2], preq->magic[3]); + goto err; + } + if (!(preq->cmd[0].cid&RCCD_CMD_BLOCK) && + (ret != (int)(preq->len + strlen(RCCD_MAGIC)))) { + DBGW("Incorrect total length: %d,%d for cid=%02x", preq->len, ret, preq->cmd[0].cid); + goto err; + } + + if (preq->cmd[0].cid < RCCD_CMD_BLOCK) + return ret; + + int sz = sizeof(struct rccd_request); + DBG("[%d] rccd_request size = %d\n", pc->pcounter,sz); + struct rccd_cmd_alsa *a = (void *)(preq->cmd); + struct cfw_block *b = (void *)(preq->cmd[0].data); + switch (preq->cmd[0].cid) { + case RCCD_CMD_BLOCK: + sz += sizeof(struct rccd_cmd) + CFW_BLOCK_SIZE(b->ncmds); + DBG("[%d] cid = RCCD_CMD_BLOCK size = %d\n", pc->pcounter,sz); + break; + case RCCD_CMD_OPEN: + case RCCD_CMD_CLOSE: + case RCCD_CMD_START: + case RCCD_CMD_STOP: + case RCCD_CMD_CAPTURE: + sz += sizeof(struct rccd_cmd_alsa); + DBG("[%d] cid = RCCD_CMD_CAPTURE size = %d\n", pc->pcounter,sz); + break; + case RCCD_CMD_PLAY: + sz += sizeof(struct rccd_cmd_alsa) + a->buffer_size; + DBG("[%d] cid = RCCD_CMD_PLAY size = %d\n", pc->pcounter,sz); + break; + case RCCD_CMD_MGET: + case RCCD_CMD_MSET: + case RCCD_CMD_NCTLS: + case RCCD_CMD_CTL: + sz += sizeof(struct rccd_cmd_alsa) + 256 * 2; + DBG("[%d] cid = RCCD_CMD_MGET size = %d\n", pc->pcounter,sz); + break; + default: + DBGW("Unknown command cid=%02x", preq->cmd[0].cid); + goto err; + } + if (sz > max) + goto err; + p += ret; + DBG("[%d] Got %d out of %d bytes", pc->pcounter, ret, sz); + +#if 0 + while (ret < sz) { + DBG("\t%d bytes left", sz - ret); + int rsz; + if ((rsz = recv(sock, p, sz - ret, 0)) <= 0) + goto err; + ret += rsz; + } +#endif + return ret; +err: + if (ret < 0) + return ret; + return 0; +} + +void *handle_client(void *p) +{ + struct rccd_hdl *pc = p; + int sock = pc->clientsock; + u8 *buffer = pc->buffer; + int n; + + DBGI("Client thread started"); + int is_ping = 0; + + /* Receive message */ + while ((n = get_packet(pc, buffer, RCCD_MAX_PACKET, &is_ping)) > 0) + { + + struct rccd_request *preq = (void *)buffer; + int off = offsetof(struct rccd_request, cmd); + if (is_ping == 0){ + DBGI("Processing Packet"); + + int c = rccd_cmd(pc, (struct rccd_cmd *)(buffer + off), n - off); + send(sock, buffer, off + c, 0); + } + else + { + DBGI("Pinging .."); + int len = sizeof(preq->magic); + struct rccd_cmd *cmd = (struct rccd_cmd *)(buffer + off); + memcpy(&(cmd->data[1]), preq->magic, len); + send(sock, buffer, off + len, 0); + } + is_ping = 0; + } + close(sock); + + DBGI("Client disconnected"); + + free(pc); + return NULL; +} + +void sig_exit(int sig) +{ + DBGW("SIGTERM received. Exiting.0x%x",sig); + exit(0); +} + +void daemonize(char *const argv[]) +{ + int i, err, pid; + DBGI("%s", argv[0]); + if (getppid() == 1) { + DBGI("RCCD2 running in background (PID %d)", getpid()); + /* already a daemon */ + return; + } + for (;;) { + if ((pid = fork()) < 0) + DBGF("Fork error"); + if (pid <= 0) + break; + // Parent + sleep(1); + if ((err = waitpid(pid, NULL, WNOHANG)) == 0) { + DBGW("Parent: Fork successful. Exiting"); + exit(0); + } + if (err < 0) { + DBGF("Unknown error"); + } + + DBGW("Android killed my baby! Baby's ID = %d",pid); + } + if (setsid() < 0) + error("Unable to daemonize"); + DBGI("Child running %d", getpid()); + setsid(); + DBGI("setsid done"); + /* close standard I/O */ + for (i = 0; i <= 2; ++i) + close(i); + if (0 != open("/dev/null", O_RDWR)) + DBGF("Unexpected error"); + dup(0); dup(0); + DBG("Closed all descriptors"); + + + signal(SIGCHLD, SIG_IGN); + signal(SIGTSTP, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGHUP, SIG_IGN); + /* catch kill signal */ + signal(SIGTERM, sig_exit); +} + +int read_pid(char *dname) +{ + int ret; + char *e, *b = strrchr(dname, '/'); + if (b) + b++; + else + b = dname; + ret = strtol(b, &e, 10); + if (*e) + return -1; + return ret; +} + +int find_server(void) +{ + DIR *fd; + struct dirent *fdf; + static int found = 0; + int pid; + char ln[64]; + FILE *fp; + + if (!(fd = opendir("/proc"))) + error("Unable to open /proc"); + while ((fdf = readdir(fd))) { + if ((pid = read_pid(fdf->d_name)) < 0) + continue; + if (pid == getpid()) + continue; + sprintf(ln, "/proc/%d/cmdline", pid); + if (!(fp = fopen(ln, "rb"))) + continue; + if (!fgets(ln, sizeof(ln), fp)) { + fclose(fp); + continue; + } + if (strstr(ln, "rccd2")) { + DBGW("Found rccd process with pid %d", pid); + ++found; + return pid; + } + } + closedir(fd); + DBGI("No %srunning rccd2 processes found", found ? "more " : ""); + return 0; +} + +void kill_server(void) +{ + int pid; + + while ((pid = find_server())) { + DBGW("Killing rccd process with pid %d", pid); + kill(pid, SIGTERM); + } + exit(0); +} + +const struct option options[] = { + { "help", 0, 0, 'h' }, + { "verbose", 1, 0, 'v' }, + { "device", 1, 0, 'd' }, + { "codec-device", 0, 0, 'c' }, + { "port", 1, 0, 'p' }, + { "kill-server", 0, 0, 'k' }, + { "safe-mode", 0, 0, 's' }, + { "super-safe", 0, 0, 'S' }, + { "dump", 0, 0, 'D' }, + { 0, 0, 0, 0 } +}; + +void usage(int ret) +{ + FILE *f = stdout; + if (ret) + f = stderr; + fprintf(f, + "Usage: rccd2 [OPTIONS]\n" + " Start the Remote CodecControl Server Daemon\n" + "Options:\n" + " --help, -h Print this help\n" + " --verbose=N, -v N Set verbose level\n" + " --safe-mode, -s Use safe mode (do not fork())\n" + " --super-safe, -S Play super safe.\n" + " No fork(), no concurrent connections\n" + " --port=N, -p N Port number on which to listen\n" + " (Default: %d)\n" + " --kill-server, -k Kill any running instance of rccd2\n" + " --dump, -D Provide a log of commands as they are executed.\n" + " --device= Open as the device node\n" + " -d \n" + " --fwid=, -f Set firmware id\n" + " (Default: \"%s\")\n" + "\n" + " [See \"acxrun -h\" for additional help on \"--device\" and]\n" + " [\"--codec-device\" options. ]\n", + DEFAULT_PORT, DEFAULT_FWID); + exit(ret); +} + +int main(int argc, char *argv[]) +{ + int serversock, clientsock; + struct sockaddr_in echoserver, echoclient; + int fCtrl, i = 0, opt, safe = 0, card = 0; + int port = DEFAULT_PORT; + char *device = NULL, *fwid = DEFAULT_FWID; + char *opts = make_opts(options); + pthread_mutex_t *mutex = ALLOC(sizeof(pthread_mutex_t)); + pthread_mutex_init(mutex, NULL); + + DBGI("[DMSG] %s pid=%d ppid=%d", argv[0], getpid(), getppid()); + while ((opt = getopt_long(argc, argv, opts, options, &i)) != -1) { + switch (opt) { + case 'h': + usage(0); + break; + case 'v': + verbose = atoi(optarg); + break; + case 'd': + device = strdup(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'k': + kill_server(); + break; + case 's': + safe = 1; + break; + case 'D': + dump_cmds = 1; + break; + case 'S': + safe = 2; + break; + case 'r': + card = atoi(optarg); + break; + case 'f': + fwid = strdup(optarg); + break; + default: + usage(1); + } + } + while (optind < argc) + DBGW("Extra command line argument \"%s\". Ignored", argv[optind++]); + + if (getppid() != 1 && (i = find_server())) + DBGF("RCCD2 is already running (pid %d)", i); + + if (!safe) { + daemonize(argv); + DBG("Running as daemon"); + } + + DBGW("Opening Device"); + //vishnu + fCtrl = open_device(device); + + /* Create the TCP socket */ + if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + DBGF("Failed to create socket"); + /* Construct the server sockaddr_in structure */ + /* Clear struct */ + memset(&echoserver, 0, sizeof(echoserver)); + /* Internet/IP */ + echoserver.sin_family = AF_INET; + /* Incoming addr */ + echoserver.sin_addr.s_addr = htonl(INADDR_ANY); + /* server port */ + echoserver.sin_port = htons(port); + + /* Bind the server socket */ + DBGW("Bind Server Socket"); + if (bind(serversock, (struct sockaddr *)&echoserver, sizeof(echoserver)) < 0) + DBGF("Failed to bind the server socket"); + + /* Listen on the server socket */ + if (listen(serversock, MAXPENDING) < 0) + DBGF("Failed to listen on server socket"); + + /* Run until cancelled */ + while (1) { + socklen_t clientlen = sizeof(echoclient); + DBGI("Waiting for client connection..."); + /* Wait for client connection */ + if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient, + &clientlen)) < 0) + DBGF("Failed to accept client connection"); + DBGI("Client connected: %s", inet_ntoa(echoclient.sin_addr)); + struct rccd_hdl *p = ALLOC(sizeof(struct rccd_hdl) + sizeof(union cfw_cmd)*BUFFSIZE); + pthread_t tid; + strcpy(p->fwid, fwid); + p->clientsock = clientsock; + p->fCtrl = fCtrl; + p->mutex = mutex; + /* Pass mutex as well */ + if (safe > 1) + { + DBG("Entering Safe Mode"); + handle_client(p); + } + else + { + DBG("Starting in thread"); + + if (pthread_create(&tid, NULL, handle_client, p) != 0) + DBGF("Error creating thread"); + } + } +} diff --git a/rccd2/rccd2.sh b/rccd2/rccd2.sh new file mode 100755 index 0000000..3b2fcc2 --- /dev/null +++ b/rccd2/rccd2.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +ADB=adb +RCCD2=rccd2 +PORT=5000 +CARD=0 +DEBUG=1 +LOGCAT=1 +SAFE="" +DEBUG_OPTS= + +usage() { + echo "usage goes here" + exit 0 +} + +while getopts "p:c:a:r:dlsh" opt; do + case $opt in + h) usage ;; + p) PORT=$OPTARG ;; + c) CARD=$OPTARG ;; + a) ADB=$OPTARG ;; + r) RCCD2=$OPTARG ;; + d) DEBUG=1 ; DEBUG_OPTS="-v 10";; + l) LOGCAT=1 ;; + s) SAFE=-s ;; + esac +done + +if [ "$DEBUG" -eq "1" ] +then + echo "PORT=$PORT" + echo "CARD=$CARD" + echo "ADB=$ADB" + echo "RCCD2=$RCCD2" + echo "SAFE=$SAFE" + echo "LOGCAT=$LOGCAT" +fi + +${ADB} root +${ADB} remount +${ADB} shell svc power stayon true +sleep 3 +${ADB} push "$RCCD2" /system/bin/rccd2 +${ADB} shell chmod 0777 /system/bin/rccd2 +${ADB} forward tcp:${PORT} tcp:${PORT} +${ADB} shell rccd2 -k +${ADB} shell rccd2 --port=${PORT} --card=${CARD} ${SAFE} ${DEBUG_OPTS} -v 4 +if [ "$DEBUG" -eq "1" ] +then + echo "RCCD2 is running..." +fi + +if [ "$LOGCAT" -eq "1" ] +then + ${ADB} logcat -s aic3xxx +fi + + diff --git a/rccd2/utils.c b/rccd2/utils.c new file mode 100755 index 0000000..7495a66 --- /dev/null +++ b/rccd2/utils.c @@ -0,0 +1,79 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +#include +#include +#include + +int verbose = 1; +void error(char *fmt, ...) +{ + va_list ap; + fprintf(stderr, "error: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(2); +} +void warn(char *fmt, ...) +{ + va_list ap; + if (verbose <= 0) + return; + fprintf(stderr, "warning: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} +void dbg(const char *f, int ln, char *fmt, ...) +{ + va_list ap; + if (getenv("MKCFW_VERBOSITY")) + verbose = atoi(getenv("MKCFW_VERBOSITY")); + if (verbose <= 1) + return; + fprintf(stderr, "DBG[%16s:%3d]: ", f, ln); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} +void *safe_alloc(const char *fn, const char *file, int ln, int n) +{ + void *ret = calloc(n, 1); + if (!ret) + error("out of memory: request for %d bytes from function %s() [%s:%d]", + n, fn, file, ln); + return ret; +} +void safe_snprintf(char *str, size_t size, const char *format, ...) +{ + char *t = ALLOC(size); + va_list ap; + va_start(ap, format); + vsnprintf(t, size, format, ap); + va_end(ap); + strcpy(str, t); + free(t); +} +char *make_opts(const struct option *options) +{ + int i = 0; + static char opts[256]; + while (options[i].name) { + safe_snprintf(opts, sizeof(opts), "%s%c%s%s", opts, options[i].val, + options[i].has_arg?":":"", + (options[i].has_arg == 2)?":":""); + ++i; + } + return opts; +} diff --git a/Android.mk b/ti_audio/Android.mk similarity index 81% rename from Android.mk rename to ti_audio/Android.mk index f1638c9..6597f47 100755 --- a/Android.mk +++ b/ti_audio/Android.mk @@ -6,11 +6,11 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := main.c -LOCAL_C_INCLUDES := external/ti_audio_s/ +LOCAL_C_INCLUDES := external/ti_audio/ LOCAL_CFLAGS := -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -LOCAL_MODULE := ti_audio_s +LOCAL_MODULE := ti_audio LOCAL_MODULE_TAGS := debug LOCAL_SYSTEM_SHARED_LIBRARIES := libc libm diff --git a/CleanSpec.mk b/ti_audio/CleanSpec.mk similarity index 100% rename from CleanSpec.mk rename to ti_audio/CleanSpec.mk diff --git a/main.c b/ti_audio/main.c similarity index 100% rename from main.c rename to ti_audio/main.c diff --git a/ti_audio.h b/ti_audio/ti_audio.h similarity index 100% rename from ti_audio.h rename to ti_audio/ti_audio.h