summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (from parent 1: 150cacd)
raw | patch | inline | side by side (from parent 1: 150cacd)
author | a0220410 <peter-li@ti.com> | |
Mon, 26 Dec 2016 10:55:10 +0000 (18:55 +0800) | ||
committer | a0220410 <peter-li@ti.com> | |
Mon, 26 Dec 2016 10:55:10 +0000 (18:55 +0800) |
16 files changed:
rccd2/Android.mk | [new file with mode: 0755] | patch | blob |
rccd2/Makefile | [new file with mode: 0755] | patch | blob |
rccd2/android_utils.c | [new file with mode: 0755] | patch | blob |
rccd2/include/aic3xxx_cfw.h | [new file with mode: 0755] | patch | blob |
rccd2/include/android_utils.h | [new file with mode: 0755] | patch | blob |
rccd2/include/host_compile.h | [new file with mode: 0755] | patch | blob |
rccd2/include/rccd2.h | [new file with mode: 0755] | patch | blob |
rccd2/include/utils.h | [new file with mode: 0755] | patch | blob |
rccd2/rccd2.bat | [new file with mode: 0755] | patch | blob |
rccd2/rccd2.c | [new file with mode: 0755] | patch | blob |
rccd2/rccd2.sh | [new file with mode: 0755] | patch | blob |
rccd2/utils.c | [new file with mode: 0755] | patch | blob |
ti_audio/Android.mk | [moved from Android.mk with 81% similarity] | patch | blob | history |
ti_audio/CleanSpec.mk | [moved from CleanSpec.mk with 100% similarity] | patch | blob | history |
ti_audio/main.c | [moved from main.c with 100% similarity] | patch | blob | history |
ti_audio/ti_audio.h | [moved from ti_audio.h with 100% similarity] | patch | blob | history |
diff --git a/rccd2/Android.mk b/rccd2/Android.mk
--- /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
--- /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
--- /dev/null
+++ b/rccd2/android_utils.c
@@ -0,0 +1,526 @@
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <sys/ioctl.h>\r
+#include <linux/kdev_t.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <time.h>\r
+#include <errno.h>\r
+#include "utils.h"\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+\r
+#include "aic3xxx_cfw.h"\r
+#include "utils.h"\r
+#include "host_compile.h"\r
+#include "android_utils.h"\r
+\r
+int dump_cmds = 0;\r
+int mode = mode_undef;\r
+\r
+static int dev_fd, dev_no, modern;\r
+\r
+#define DEVICE_ID 98\r
+\r
+int regDumpId;\r
+char regBuffer[512];\r
+\r
+//static char *device;\r
+void diag(int lvl, char *fmt, ...)\r
+{\r
+ va_list ap;\r
+ va_start(ap, fmt);\r
+#ifdef ANDROID\r
+ __android_log_vprint(lvl, PROGRAM, fmt, ap);\r
+#endif\r
+ va_end(ap);\r
+ if (getppid() != 1 && (lvl >= (ANDROID_LOG_ERROR - verbose))) {\r
+ va_start(ap, fmt);\r
+ vfprintf(stderr, fmt, ap);\r
+ va_end(ap);\r
+ fprintf(stderr, "\n");\r
+ }\r
+ if (lvl >= ANDROID_LOG_FATAL)\r
+ exit(1);\r
+}\r
+\r
+const struct { char *node; int cfwb; } devices[] = {\r
+ { "aic3xxx_cfw", 1 },\r
+ { "tiload", 0 },\r
+ { "tiload_node", 0 }\r
+};\r
+int open_device(char *device)\r
+{\r
+ char dfile[64];\r
+ struct stat sbuf;\r
+ int i = 0, fd;\r
+ if (device) {\r
+ // Possible use on host\r
+ DBGW("Device not null");\r
+ if (stat(device, &sbuf) == 0) {\r
+ strncpy(dfile, device, sizeof(dfile)-1);\r
+ goto open;\r
+ }\r
+ DBGW("Could not locate device \"%s\"", device);\r
+ // Switch exclusive to old style device if one is specified (rccd backwards-compatibilty)\r
+ while (devices[i].cfwb)\r
+ ++i;\r
+ }\r
+ for (; i < ARRAY_LEN(devices); ++i) {\r
+ sprintf(dfile, "/dev/%s", devices[i].node);\r
+ if (stat(dfile, &sbuf) == 0)\r
+ goto open;\r
+ DBGW("Missing device node \"%s\"\n\tLooking for %s in /proc/devices...", dfile, devices[i].node);\r
+ FILE *fp = fopen("/proc/devices", "r");\r
+ if (!fp)\r
+ DBGF("Unable to read /proc/devices");\r
+ char ln[4096];\r
+ while (fgets(ln, sizeof(ln), fp)) {\r
+ if (!strstr(ln, devices[i].node))\r
+ continue;\r
+ ln[strlen(ln) - 1] = 0;\r
+ DBGW("Found node entry \"%s\"", ln);\r
+ int major = strtol(ln, NULL, 10);\r
+ DBGW("\tMajor number = %d", major);\r
+ if (mknod(dfile, S_IFCHR | 0777, MKDEV(major, 0)) < 0)\r
+ DBGF("Unable to\n\tmknod \"%s\" c %d 0", dfile, major);\r
+ goto open;\r
+ }\r
+ }\r
+ //This was DBGF \r
+ DBGW("Unable find entry for codec diagnostic device. Please check\n"\r
+ "\tcat /proc/devices");\r
+\r
+\r
+ // CUstom code \r
+ //dfile = "/sdcard/RCCD2/Test.dev";\r
+ sprintf(dfile, "/sdcard/RCCD2/Test.dev");\r
+ i = 4;\r
+ DBGW("Device open is redirected to a file now - /sdcard/RCCD2/Test.dev");\r
+ goto open;\r
+\r
+\r
+ return -1;\r
+open:\r
+ if ((fd = open(dfile, O_RDWR, 0)) < 0)\r
+ DBGF("Unable to open device %s", dfile);\r
+ modern = devices[i].cfwb;\r
+ if (!modern) {\r
+ // This stuff below is needed on the old tiload device \r
+ // for purposes I don't fully understand\r
+ char magic[4];\r
+ ioctl(fd, _IOR(0xE0, 3, int), magic);\r
+ }\r
+ dev_fd = fd;\r
+ dev_no = i;\r
+ if (mode == mode_undef)\r
+ mode = devices[i].cfwb ? mode_kernel : mode_user;\r
+ DBG("Opened device %s, mode:%s", dfile, modern ? "modern" : "legacy");\r
+ return fd;\r
+}\r
+\r
+static int cbook = -1, cpage = -1, lock = 0;\r
+\r
+\r
+static void mread_reg(union cfw_register reg, u8 *buf, int n)\r
+{\r
+ int ncmds = CFW_CMD_BURST_LEN(n);\r
+ int err, sz = CFW_BLOCK_SIZE(ncmds);\r
+ struct cfw_block *blk = ALLOC(sz);\r
+ blk->ncmds = ncmds;\r
+ blk->cmd[0].bhdr.cid = CFW_CMD_RBURST;\r
+ blk->cmd[0].bhdr.len = n;\r
+ blk->cmd[1].reg = reg;\r
+ if ((err = read(dev_fd, blk, sz)) != sz)\r
+ DBGF("Device read error %d", err);\r
+ memcpy(buf, blk->cmd[1].burst.data, n);\r
+}\r
+\r
+static void mwrite_reg(union cfw_register reg, const u8 *buf, int n)\r
+{\r
+ int ncmds = (n <= 3) ? n : CFW_CMD_BURST_LEN(n);\r
+ int i, err, sz = CFW_BLOCK_SIZE(ncmds);\r
+ struct cfw_block *blk = ALLOC(sz);\r
+ blk->ncmds = ncmds;\r
+ if (n <= 3) {\r
+ for (i = 0; i < n; ++i) {\r
+ blk->cmd[i].reg = reg;\r
+ blk->cmd[i].reg.offset = reg.offset + i;\r
+ blk->cmd[i].reg.data = buf[i + 1];\r
+ }\r
+ }\r
+ else {\r
+ blk->cmd[0].bhdr.cid = CFW_CMD_BURST;\r
+ blk->cmd[0].bhdr.len = n;\r
+ blk->cmd[1].reg = reg;\r
+ memcpy(blk->cmd[1].burst.data, buf + 1, n);\r
+ }\r
+ if ((err = write(dev_fd, blk, sz)) != sz)\r
+ DBGF("Device write error %d", err);\r
+}\r
+\r
+\r
+#define DREAD(reg, b, n) do { \\r
+ int err_ret__; \\r
+ DBGI("r 0x%02x 0x%02x, modern:%d", (b)[0], (n), modern); \\r
+ sprintf(regBuffer, "\nr %d %02x %02x%c", DEVICE_ID, (b)[0], (n),'\0'); \\r
+ write(regDumpId, ®Buffer, strlen(regBuffer)); \\r
+if (modern) {\\r
+ mread_reg(reg, (b), n); \\r
+}else if ((err_ret__ = read(dev_fd, b, n)) != n) \\r
+ DBGF("Device read error %d", err_ret__); \\r
+} while (0)\r
+#define DWRITE(reg, b, n) do { \\r
+ int err_ret__, i__; \\r
+ DBGI("w 0x%02x 0x%02x", (b)[0], (b)[1]); \\r
+ sprintf(regBuffer, "\nw %d %02x %02x%c", DEVICE_ID, (b)[0], (b)[1], '\0'); \\r
+ write(regDumpId, ®Buffer, strlen(regBuffer)); \\r
+for (i__ = 2; i__ < n; ++i__) \\r
+{DBGI("> 0x%02x", (b)[i__]); \\r
+ sprintf(regBuffer, " %02x%c", (b)[i__],'\0'); \\r
+ write(regDumpId, ®Buffer, strlen(regBuffer)); }\\r
+if (modern) {\\r
+ mwrite_reg(reg, b, n); \\r
+}else if ((err_ret__ = write(dev_fd, b, n)) != n) \\r
+ DBGF("Device write error %d", err_ret__); \\r
+} while (0)\r
+\r
+static void cfw_lock(int l)\r
+{\r
+ if (l && !lock) {\r
+ // FIXME dummy\r
+ lock = 1;\r
+ }\r
+ else if (!l && lock) {\r
+ lock = 0;\r
+ }\r
+}\r
+static int restore_lock;\r
+static void setpb(union cfw_register r)\r
+{\r
+ DBG("Enter setpb");\r
+ u8 data[2];\r
+ restore_lock = lock;\r
+ cfw_lock(1);\r
+ DBG("Set Page/Book: (0x%02x,0x%02x)", r.book, r.page);\r
+ // if (cbook != r.book) {\r
+ if (1){\r
+ //if (cpage != 0) { \r
+ if (1){\r
+ data[0] = data[1] = 0;\r
+ if (!modern)\r
+ DWRITE(r, data, 2);\r
+ cpage = 0;\r
+ }\r
+ data[0] = 0x7F; data[1] = r.book;\r
+ if (!modern)\r
+ DWRITE(r, data, 2);\r
+ cbook = r.book;\r
+ DBG("Set Book: [0x%02x]", r.book);\r
+ }\r
+\r
+ //if (cpage != r.page) {\r
+ if (1){ \r
+ data[0] = 0; data[1] = r.page;\r
+ if (!modern)\r
+ DWRITE(r, data, 2);\r
+ cpage = r.page;\r
+ DBG("Set Page: [0x%02x]", r.page);\r
+ }\r
+ DBG("Exit setpb");\r
+}\r
+static void unsetpb(void)\r
+{\r
+ DBG("Enter unsetpb");\r
+ cfw_lock(restore_lock);\r
+ DBG("Exit unsetpb");\r
+}\r
+\r
+static u8 reg_read(union cfw_register reg)\r
+{\r
+ u8 ret;\r
+ ret = reg.offset;\r
+ setpb(reg);\r
+ mread_reg(reg, &ret, 1);\r
+\r
+ DREAD(reg, &ret, 1);\r
+ unsetpb();\r
+ return ret;\r
+}\r
+static void reg_write(union cfw_register reg)\r
+{\r
+ u8 data[2];\r
+ data[0] = reg.offset;\r
+ data[1] = reg.data;\r
+ setpb(reg);\r
+ DWRITE(reg, data, 2);\r
+ unsetpb();\r
+}\r
+static void reg_wait(union cfw_register reg, u8 mask, u8 data)\r
+{\r
+ u8 cur = reg_read(reg);\r
+ while ((cur & mask) != data) {\r
+ usleep(2000);\r
+ cur = reg_read(reg);\r
+ }\r
+}\r
+static int set_bits(u8 *data, u8 mask, u8 val)\r
+{\r
+ u8 nd;\r
+ nd = ((*data&(~mask)) | (mask&val));\r
+ if (nd == *data)\r
+ return 0;\r
+ *data = nd;\r
+ return 1;\r
+}\r
+static void cfw_op(unsigned char *var, struct cfw_cmd_op cmd)\r
+{\r
+ u32 op1, op2;\r
+ u32 cid = cmd.cid;\r
+\r
+ op1 = cmd.op1;\r
+ op2 = cmd.op2;\r
+ if (cid&CFW_CMD_OP1_ID)\r
+ op1 = var[op1];\r
+ if (cid&CFW_CMD_OP2_ID)\r
+ op2 = var[op2];\r
+ cid &= ~(CFW_CMD_OP1_ID | CFW_CMD_OP2_ID);\r
+\r
+ switch (cid) {\r
+ case CFW_CMD_OP_ADD: var[cmd.dst] = op1 + op2; break;\r
+ case CFW_CMD_OP_SUB: var[cmd.dst] = op1 - op2; break;\r
+ case CFW_CMD_OP_MUL: var[cmd.dst] = op1*op2; break;\r
+ case CFW_CMD_OP_DIV: var[cmd.dst] = op1 / op2; break;\r
+ case CFW_CMD_OP_AND: var[cmd.dst] = op1 & op2; break;\r
+ case CFW_CMD_OP_OR: var[cmd.dst] = op1 | op2; break;\r
+ case CFW_CMD_OP_SHL: var[cmd.dst] = (op1 << op2); break;\r
+ case CFW_CMD_OP_SHR: var[cmd.dst] = (op1 >> op2); break;\r
+ case CFW_CMD_OP_RR:\r
+ while (op2--) {\r
+ var[cmd.dst] = (op1 >> 1) | ((op1 & 1) << 7);\r
+ }\r
+ break;\r
+ case CFW_CMD_OP_XOR: var[cmd.dst] = op1 ^ op2; break;\r
+ case CFW_CMD_OP_NOT: var[cmd.dst] = ~op1; break;\r
+ case CFW_CMD_OP_LNOT: var[cmd.dst] = !op1; break;\r
+ default: break;\r
+ }\r
+}\r
+\r
+static int bulk_write(union cfw_register reg, int count, const u8 *buf)\r
+{\r
+ setpb(reg);\r
+ DWRITE(reg, buf - 1, count + 1);\r
+ unsetpb();\r
+ return 0;\r
+}\r
+\r
+static int bulk_read(union cfw_register reg, int count, u8 *buf)\r
+{\r
+ int i;\r
+ if (reg.offset != buf[-1]) {\r
+ DBGW("Mismatched register offset for read (%d != %d)",\r
+ reg.offset, buf[-1]);\r
+ }\r
+ buf[0] = reg.offset;\r
+\r
+ if (reg.offset == 0xFF && reg.book == 0xFF && reg.page == 0xFF)\r
+ {\r
+ /* To handle Ping*/\r
+ buf[0] = 0x7c;\r
+ buf[1] = 00;\r
+ buf[2] = 01;\r
+ buf[3] = 02;\r
+\r
+ DBGI("..........PING.......");\r
+\r
+ }\r
+ else\r
+ {\r
+\r
+ setpb(reg);\r
+ //DBG("Commenting of DRED");\r
+ DREAD(reg, buf, count);\r
+ unsetpb();\r
+ }\r
+ DBGI("Reading from (%d,%d,%d)... %d bytes", reg.book, reg.page, reg.offset,\r
+ count);\r
+ for (i = 0; i < count; i += 8) {\r
+ switch (count - i) {\r
+ case 1: DBGI("# 0x%02x", buf[i + 0]); break;\r
+ case 2: DBGI("# 0x%02x 0x%02x", buf[i + 0], buf[i + 1]); break;\r
+ case 3: DBGI("# 0x%02x 0x%02x 0x%02x", buf[i + 0], buf[i + 1], buf[i + 2]); break;\r
+ case 4: DBGI("# 0x%02x 0x%02x 0x%02x 0x%02x", buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3]); break;\r
+ 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;\r
+ 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;\r
+ 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;\r
+ 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;\r
+ }\r
+ }\r
+\r
+\r
+ return 0;\r
+}\r
+\r
+static void run_block_slow(struct cfw_block *pb, u8 *var)\r
+{\r
+ int pc = 0;\r
+ int cond = 0;\r
+ u8 data;\r
+// int i;\r
+ \r
+ DBG("%s: pb->ncmds=%d", __FUNCTION__, pb->ncmds);\r
+ while (pc < pb->ncmds) {\r
+ union cfw_cmd *c = &(pb->cmd[pc]);\r
+ if (c->cid != CFW_CMD_BRANCH_IM &&\r
+ c->cid != CFW_CMD_BRANCH_ID &&\r
+ c->cid != CFW_CMD_NOP)\r
+ cond = 0;\r
+ DBGI("%s: Case No %d:", __FUNCTION__, c->cid);\r
+ switch (c->cid) {\r
+\r
+ case 0 ... (CFW_CMD_NOP - 1) :\r
+ DBGI("CFW_CMD_NOP-1");\r
+ reg_write(c->reg);\r
+ pc += 1;\r
+ break;\r
+ case CFW_CMD_NOP:\r
+ DBGI("CFW_CMD_NOP");\r
+ pc += 1;\r
+ break;\r
+ case CFW_CMD_DELAY:\r
+ DBGI("CFW_CMD_DELAY");\r
+ usleep(c->delay.delay * 1000 + c->delay.delay_fine * 4);\r
+ pc += 1;\r
+ break;\r
+ case CFW_CMD_UPDTBITS:\r
+ DBGI("CFW_CMD_UPDTBITS");\r
+ c[1].reg.data = reg_read(c[1].reg);\r
+ set_bits(&data, c->bitop.mask, c[1].reg.data);\r
+ reg_write(c[1].reg);\r
+ pc += 2;\r
+ break;\r
+ case CFW_CMD_WAITBITS:\r
+ DBGI("CFW_CMD_WAITBITS");\r
+ reg_wait(c[1].reg, c->bitop.mask, c[1].reg.data);\r
+ pc += 2;\r
+ break;\r
+ case CFW_CMD_LOCK:\r
+ DBGI("CFW_CMD_LOCK");\r
+ cfw_lock(c->lock.lock);\r
+ pc += 1;\r
+ break;\r
+ case CFW_CMD_BURST:\r
+ DBGI("CFW_CMD_BURST");\r
+ bulk_write(c[1].reg, c->bhdr.len,\r
+ c[1].burst.data);\r
+ pc += CFW_CMD_BURST_LEN(c->bhdr.len);\r
+ break;\r
+ case CFW_CMD_RBURST:\r
+ DBGI("CFW_CMD_RBURST");\r
+ bulk_read(c[1].reg, c->bhdr.len,\r
+ c[1].burst.data);\r
+ pc += CFW_CMD_BURST_LEN(c->bhdr.len);\r
+ break;\r
+ case CFW_CMD_LOAD_VAR_IM:\r
+ set_bits(&var[c->ldst.dvar],\r
+ c->ldst.mask, c->ldst.svar);\r
+ pc += 1;\r
+ break;\r
+ case CFW_CMD_LOAD_VAR_ID:\r
+ if (c->ldst.svar != c->ldst.dvar) {\r
+ set_bits(&var[c->ldst.dvar],\r
+ c->ldst.mask, var[c->ldst.svar]);\r
+ pc += 1;\r
+ }\r
+ else {\r
+ data = reg_read(c[1].reg);\r
+ set_bits(&var[c->ldst.dvar],\r
+ c->ldst.mask, data);\r
+ pc += 2;\r
+ }\r
+ break;\r
+ case CFW_CMD_STORE_VAR:\r
+ if (c->ldst.svar != c->ldst.dvar) {\r
+ c[1].reg.data = reg_read(c[1].reg);\r
+ set_bits(&(c[1].reg.data),\r
+ var[c->ldst.dvar],\r
+ var[c->ldst.svar]);\r
+ reg_write(c[1].reg);\r
+ }\r
+ else {\r
+ c[1].reg.data = reg_read(c[1].reg);\r
+ set_bits(&data, c->ldst.mask,\r
+ var[c->ldst.svar]);\r
+ reg_write(c[1].reg);\r
+ }\r
+ pc += 2;\r
+ break;\r
+ case CFW_CMD_COND:\r
+ cond = var[c->cond.svar] & c->cond.mask;\r
+ pc += 1;\r
+ break;\r
+ case CFW_CMD_BRANCH:\r
+ pc = c->branch.address;\r
+ break;\r
+ case CFW_CMD_BRANCH_IM:\r
+ if (c->branch.match == cond)\r
+ pc = c->branch.address;\r
+ else\r
+ pc += 1;\r
+ break;\r
+ case CFW_CMD_BRANCH_ID:\r
+ if (var[c->branch.match] == cond)\r
+ pc = c->branch.address;\r
+ else\r
+ pc += 1;\r
+ break;\r
+ case CFW_CMD_PRINT:\r
+ {\r
+ union cfw_cmd *parglist = c + CFW_CMD_PRINT_ARG(c->print);\r
+#ifdef ANDROID\r
+ DBGI(c->print.fmt,\r
+ var[parglist->print_arg[0]],\r
+ var[parglist->print_arg[1]],\r
+ var[parglist->print_arg[2]],\r
+ var[parglist->print_arg[3]]);\r
+#else\r
+ printf(c->print.fmt,\r
+ var[parglist->print_arg[0]],\r
+ var[parglist->print_arg[1]],\r
+ var[parglist->print_arg[2]],\r
+ var[parglist->print_arg[3]]);\r
+#endif\r
+ pc += CFW_CMD_PRINT_LEN(c->print);\r
+ }\r
+ break;\r
+ case CFW_CMD_OP_START ... CFW_CMD_OP_END:\r
+ cfw_op(var, c->op);\r
+ pc += 1;\r
+ break;\r
+ default:\r
+ DBGW("Unknown cmd command %x. Skipped", c->cid);\r
+ pc += 1;\r
+ break;\r
+ }\r
+ }\r
+\r
+}\r
+\r
+void run_block(struct cfw_block *pb, u8 *var)\r
+{\r
+ char *filePath = "/sdcard/RCCD2/regDump.txt";\r
+ if (!modern || (mode != mode_kernel)) {\r
+ DBGI("Calling run block slow");\r
+ regDumpId = open(filePath, O_RDWR | O_APPEND | O_CREAT, 0644);\r
+ run_block_slow(pb, var);\r
+ close(regDumpId);\r
+ return;\r
+ }\r
+ int r, n = CFW_BLOCK_SIZE(pb->ncmds);\r
+ 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));\r
+ if ((r = write(dev_fd, pb, n)) != n)\r
+ DBGF("Device write error %d", r);\r
+\r
+}\r
diff --git a/rccd2/include/aic3xxx_cfw.h b/rccd2/include/aic3xxx_cfw.h
--- /dev/null
@@ -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 <asm-generic/int-ll64.h>
+#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) /**<Max length of string identifies*/
+# define CFW_MAX_VARS (256) /**<Number of "variables" alive at the*/
+/**<same time in an acx file*/
+#endif
+/* @} */
+/** \defgroup st Enums, Flags, Macros and Supporting Types */
+/* @{ */
+/**
+* Device Family Identifier
+*
+*/
+enum __attribute__((__packed__)) cfw_dfamily{
+ CFW_DFM_TYPE_A,
+ CFW_DFM_TYPE_B,
+ CFW_DFM_TYPE_C
+};
+/**
+* Device Identifier
+*
+*/
+enum __attribute__((__packed__)) cfw_device{
+ CFW_DEV_DAC3120,
+ CFW_DEV_DAC3100,
+ CFW_DEV_AIC3120,
+ CFW_DEV_AIC3100,
+ CFW_DEV_AIC3110,
+ CFW_DEV_AIC3111,
+ CFW_DEV_AIC36,
+ CFW_DEV_AIC3206,
+ CFW_DEV_AIC3204,
+ CFW_DEV_AIC3254,
+ CFW_DEV_AIC3256,
+ CFW_DEV_AIC3253,
+ CFW_DEV_AIC3212,
+ CFW_DEV_AIC3262,
+ CFW_DEV_AIC3017,
+ CFW_DEV_AIC3008,
+ CFW_DEV_AIC3266,
+ CFW_DEV_AIC3285,
+};
+/**
+* Transition Sequence Identifier
+*
+*/
+enum cfw_transition_t {
+ CFW_TRN_INIT,
+ CFW_TRN_RESUME,
+ CFW_TRN_NEUTRAL,
+ CFW_TRN_A_MUTE,
+ CFW_TRN_D_MUTE,
+ CFW_TRN_AD_MUTE,
+ CFW_TRN_A_UNMUTE,
+ CFW_TRN_D_UNMUTE,
+ CFW_TRN_AD_UNMUTE,
+ CFW_TRN_SUSPEND,
+ CFW_TRN_EXIT,
+ CFW_TRN_N
+};
+#ifndef __cplusplus
+static const char *const cfw_transition_id[] = {
+ [CFW_TRN_INIT] = "INIT",
+ [CFW_TRN_RESUME] = "RESUME",
+ [CFW_TRN_NEUTRAL] = "NEUTRAL",
+ [CFW_TRN_A_MUTE] = "A_MUTE",
+ [CFW_TRN_D_MUTE] = "D_MUTE",
+ [CFW_TRN_AD_MUTE] = "AD_MUTE",
+ [CFW_TRN_A_UNMUTE] = "A_UNMUTE",
+ [CFW_TRN_D_UNMUTE] = "D_UNMUTE",
+ [CFW_TRN_AD_UNMUTE] = "AD_UNMUTE",
+ [CFW_TRN_SUSPEND] = "SUSPEND",
+ [CFW_TRN_EXIT] = "EXIT",
+};
+#endif
+/* @} */
+/** \defgroup ds Data Structures */
+/* @{ */
+/**
+* CFW Command
+* These commands do not appear in the register
+* set of the device.
+*/
+enum __attribute__((__packed__)) cfw_cmd_id{
+ CFW_CMD_NOP = 0x80,
+ CFW_CMD_DELAY,
+ CFW_CMD_UPDTBITS,
+ CFW_CMD_WAITBITS,
+ CFW_CMD_LOCK,
+ CFW_CMD_BURST,
+ CFW_CMD_RBURST,
+ CFW_CMD_LOAD_VAR_IM,
+ CFW_CMD_LOAD_VAR_ID,
+ CFW_CMD_STORE_VAR,
+ CFW_CMD_COND,
+ CFW_CMD_BRANCH,
+ CFW_CMD_BRANCH_IM,
+ CFW_CMD_BRANCH_ID,
+ CFW_CMD_PRINT,
+ CFW_CMD_OP_ADD = 0xC0,
+ CFW_CMD_OP_SUB,
+ CFW_CMD_OP_MUL,
+ CFW_CMD_OP_DIV,
+ CFW_CMD_OP_AND,
+ CFW_CMD_OP_OR,
+ CFW_CMD_OP_SHL,
+ CFW_CMD_OP_SHR,
+ CFW_CMD_OP_RR,
+ CFW_CMD_OP_XOR,
+ CFW_CMD_OP_NOT,
+ CFW_CMD_OP_LNOT,
+};
+/**
+* CFW Delay
+* Used for the cmd command delay
+* Has one parameter of delay time in ms
+*/
+struct cfw_cmd_delay {
+ u16 delay;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 delay_fine;
+};
+/**
+* CFW Lock
+* Take codec mutex to avoid clashing with DAPM operations
+*/
+struct cfw_cmd_lock {
+ u16 lock;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 unused;
+};
+/**
+* CFW UPDTBITS, WAITBITS, CHKBITS
+* Both these cmd commands have same arguments
+* cid will be used to specify which command it is
+* has parameters of book, page, offset and mask
+*/
+struct cfw_cmd_bitop {
+ u16 unused1;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 mask;
+};
+/**
+* CFW CMD Burst header
+* Burst writes inside command array
+* Followed by burst address, first byte
+*/
+struct cfw_cmd_bhdr {
+ u16 len;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 unused;
+};
+/**
+* CFW CMD Burst
+* Burst writes inside command array
+* Followed by data to the extent indicated in previous len
+* Can be safely cast to cfw_burst
+*/
+struct cfw_cmd_burst {
+// u8 slave_id;
+ u8 book;
+ u8 page;
+ u8 offset;
+ u8 data[1];
+};
+#define CFW_CMD_BURST_LEN(n) (2 + ((n) - 1 + 3)/4)
+/**
+* CFW CMD Scratch register
+* For load
+* if (svar != dvar)
+* dvar = setbits(svar, mask) // Ignore reg
+* else
+* dvar = setbits(reg, mask)
+* For store
+* if (svar != dvar)
+* reg = setbits(svar, dvar)
+* else
+* reg = setbits(svar, mask)
+*
+*/
+struct cfw_cmd_ldst {
+ u8 dvar;
+ u8 svar;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 mask;
+};
+/**
+* CFW CMD Conditional
+* May only precede branch. Followed by nmatch+1 jump
+* instructions
+* cond = svar&mask
+* At each of the following nmatch+1 branch command
+* if (cond == match)
+* take the branch
+*/
+struct cfw_cmd_cond {
+ u8 svar;
+ u8 nmatch;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 mask;
+};
+#define CFW_CMD_COND_LEN(nm) (1 + ((nm)+1))
+/**
+* CFW CMD Goto
+* For branch, break, continue and stop
+*/
+struct cfw_cmd_branch {
+ u16 address;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 match;
+};
+/**
+* CFW Debug print
+* For diagnostics
+*/
+struct cfw_cmd_print {
+ u8 fmtlen;
+ u8 nargs;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ char fmt[1];
+};
+#define CFW_CMD_PRINT_LEN(p) (1 + ((p).fmtlen/4) + (((p).nargs + 3)/4))
+#define CFW_CMD_PRINT_ARG(p) (1 + ((p).fmtlen/4))
+/**
+* CFW Arithmetic and logical operations
+* Bit 5 indicates if op1 is indirect
+* Bit 6 indicates if op2 is indirect
+*/
+struct cfw_cmd_op {
+ u8 op1;
+ u8 op2;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 dst;
+};
+#define CFW_CMD_OP1_ID (1u<<5)
+#define CFW_CMD_OP2_ID (1u<<4)
+#define CFW_CMD_OP_START CFW_CMD_OP_ADD
+#define CFW_CMD_OP_END (CFW_CMD_OP_LNOT|CFW_CMD_OP1_ID|CFW_CMD_OP2_ID)
+#define CFW_CMD_OP_IS_UNARY(x) \
+ (((x) == CFW_CMD_OP_NOT) || ((x) == CFW_CMD_OP_LNOT))
+/**
+* CFW Register
+*
+* A single reg write
+*
+*/
+union cfw_register {
+ struct {
+ // u8 slave_id;
+ u8 book;
+ u8 page;
+ u8 offset;
+ u8 data;
+ };
+ u32 bpod;
+};
+/**
+* CFW Command
+*
+* Can be a either a
+* -# single register write, or
+* -# command
+*
+*/
+union cfw_cmd {
+ struct {
+ u16 unused1;
+ u8 cid;
+ //enum cfw_cmd_id cid;
+ u8 unused2;
+ };
+ union cfw_register reg;
+ struct cfw_cmd_delay delay;
+ struct cfw_cmd_lock lock;
+ struct cfw_cmd_bitop bitop;
+ struct cfw_cmd_bhdr bhdr;
+ struct cfw_cmd_burst burst;
+ struct cfw_cmd_ldst ldst;
+ struct cfw_cmd_cond cond;
+ struct cfw_cmd_branch branch;
+ struct cfw_cmd_print print;
+ u8 print_arg[4];
+ struct cfw_cmd_op op;
+};
+#define CFW_REG_IS_CMD(x) ((x).cid >= 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
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef ANDROID_UTILS_H_
+#define ANDROID_UTILS_H_
+
+#include "host_compile.h"
+
+#ifdef ANDROID
+#include <android/log.h>
+#include <cutils/log.h>
+#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
--- /dev/null
@@ -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 <asm-generic/int-ll64.h>
+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 <stdlib.h>
+# include "utils.h"
+# include <string.h>
+# include <assert.h>
+#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
--- /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
--- /dev/null
+++ b/rccd2/include/utils.h
@@ -0,0 +1,68 @@
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <stdio.h>
+#include <getopt.h>
+
+#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
--- /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
--- /dev/null
+++ b/rccd2/rccd2.c
@@ -0,0 +1,654 @@
+#include <stdio.h>\r
+#include <stddef.h>\r
+#include <string.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <sys/wait.h>\r
+#include <dirent.h>\r
+#include <pthread.h>\r
+#include <sys/socket.h>\r
+#include <sys/ioctl.h>\r
+#include <arpa/inet.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <signal.h>\r
+#include <netinet/in.h>\r
+#include <fcntl.h>\r
+#include <time.h>\r
+#include <getopt.h>\r
+#include "utils.h"\r
+#include "android_utils.h"\r
+#include "rccd2.h"\r
+#include "aic3xxx_cfw.h"\r
+\r
+/* Max connection requests */\r
+#define MAXPENDING (16)\r
+#define BUFFSIZE (256)\r
+#define DEFAULT_PORT (80)\r
+\r
+/* State of each independent connection */\r
+struct rccd_hdl {\r
+ u32 pcounter;\r
+ char fwid[32];\r
+ int clientsock;\r
+ int fCtrl;\r
+ pthread_mutex_t *mutex;\r
+ int slave_id,book, page;\r
+ u8 buffer[RCCD_MAX_PACKET];\r
+ struct cfw_block block;\r
+};\r
+\r
+#define CRITICAL(code_section__) do { \\r
+if (pthread_mutex_lock(pc->mutex)) \\r
+ DBGF("Error obtaining mutex lock"); \\r
+ \\r
+ code_section__; \\r
+ \\r
+if (pthread_mutex_unlock(pc->mutex)) \\r
+ DBGF("Error releasing mutex lock"); \\r
+} while (0)\r
+\r
+void legacy_read(struct rccd_hdl *pc, u8 *buf, int n)\r
+{\r
+ pc->block.ncmds = CFW_CMD_BURST_LEN(n);\r
+ pc->block.cmd[0].bhdr.cid = CFW_CMD_RBURST;\r
+ pc->block.cmd[0].bhdr.len = n;\r
+ //pc->block.cmd[1].burst.slave_id = pc->slave_id;\r
+ pc->block.cmd[1].burst.book = pc->book;\r
+ pc->block.cmd[1].burst.page = pc->page;\r
+ pc->block.cmd[1].burst.offset = buf[0];\r
+ DBG("legacy_read: (%d,%d,%d) %d bytes", pc->book, pc->page, buf[0], n);\r
+ CRITICAL(run_block(&(pc->block), NULL));\r
+ memcpy(buf + 1, pc->block.cmd[1].burst.data, n);\r
+}\r
+\r
+void legacy_write(struct rccd_hdl *pc, u8 *buf, int n)\r
+{\r
+ u8 *pd = buf;\r
+ if (buf[0] == 127) {\r
+ pc->book = buf[1];\r
+ if (n != 2)\r
+ DBGW("Received book change as part of burst command. "\r
+ "Additional writes have been ignored (n=%d)", n);\r
+ return;\r
+ }\r
+ if (buf[0] == 0) {\r
+ pc->page = buf[1];\r
+ --n;\r
+ if (n <= 1)\r
+ return;\r
+ ++pd;\r
+ pd[0] = 1;\r
+ }\r
+ pc->block.ncmds = CFW_CMD_BURST_LEN(n - 1);\r
+ pc->block.cmd[0].bhdr.cid = CFW_CMD_BURST;\r
+ pc->block.cmd[0].bhdr.len = n - 1;\r
+ //pc->block.cmd[1].burst.slave_id = pc->slave_id;\r
+ pc->block.cmd[1].burst.book = pc->book;\r
+ pc->block.cmd[1].burst.page = pc->page;\r
+ pc->block.cmd[1].burst.offset = pd[0];\r
+ memcpy(pc->block.cmd[1].burst.data, &pd[1], n - 1);\r
+ DBG("legacy_write: (%d,%d,%d) %d bytes", pc->book, pc->page, pd[0], n - 1);\r
+ CRITICAL(run_block(&(pc->block), NULL));\r
+}\r
+\r
+int rccd_cmd(struct rccd_hdl *pc, struct rccd_cmd *cmd, int len)\r
+{\r
+ DBG("Getting into rccd_cmd");\r
+ const char * const cid_str[] = {\r
+ [RCCD_CMD_READ] = "RCCD_CMD_READ",\r
+ [RCCD_CMD_WRITE] = "RCCD_CMD_WRITE",\r
+ [RCCD_CMD_SLAVE] = "RCCD_CMD_SLAVE",\r
+ [RCCD_CMD_FWID] = "RCCD_CMD_FWID",\r
+ [RCCD_CMD_BLOCK] = "RCCD_CMD_BLOCK",\r
+ [RCCD_CMD_OPEN] = "RCCD_CMD_OPEN",\r
+ [RCCD_CMD_CLOSE] = "RCCD_CMD_CLOSE",\r
+ [RCCD_CMD_PLAY] = "RCCD_CMD_PLAY",\r
+ [RCCD_CMD_CAPTURE] = "RCCD_CMD_CAPTURE",\r
+ [RCCD_CMD_START] = "RCCD_CMD_START",\r
+ [RCCD_CMD_STOP] = "RCCD_CMD_STOP",\r
+ [RCCD_CMD_MGET] = "RCCD_CMD_MGET",\r
+ [RCCD_CMD_MSET] = "RCCD_CMD_MSET",\r
+ [RCCD_CMD_NCTLS] = "RCCD_CMD_NCTLS",\r
+ [RCCD_CMD_CTL] = "RCCD_CMD_CTL",\r
+ };\r
+\r
+ DBG("%s: cid=%0x \"%s\" len=%d", __FUNCTION__, cmd->cid, cid_str[cmd->cid],\r
+ cmd->len);\r
+\r
+ //if (!pc->mixer && cmd->cid > RCCD_CMD_BLOCK)\r
+ // DBGF("Attempt to do ALSA operation when no sound card is present");\r
+\r
+ switch (cmd->cid) {\r
+ case RCCD_CMD_READ:\r
+ DBG("rccd:RCCD_CMD_READ");\r
+ if (cmd->len < 4)\r
+ break;\r
+ legacy_read(pc, cmd->data, cmd->len - 4);\r
+ break;\r
+ case RCCD_CMD_WRITE:\r
+ DBG("rccd:RCCD_CMD_WRITE");\r
+ if (cmd->len < 4)\r
+ break;\r
+ legacy_write(pc, cmd->data, cmd->len - 4 + 1);\r
+ break;\r
+ case RCCD_CMD_BLOCK:\r
+ {\r
+ DBG("rccd:RCCD_CMD_BLOCK");\r
+ u8 var[256];\r
+ struct cfw_block *b = (void *)cmd->data;\r
+ len = CFW_BLOCK_SIZE(b->ncmds) + sizeof(struct rccd_cmd);\r
+ CRITICAL(run_block(b, var));\r
+ }\r
+ break;\r
+ case RCCD_CMD_OPEN:\r
+ DBG("rccd:RCCD_CMD_OPEN - : NOT SUPPORTED");\r
+ break;\r
+ case RCCD_CMD_CLOSE:\r
+ DBG("rccd:RCCD_CMD_CLOSE - : NOT SUPPORTED");\r
+ break;\r
+ case RCCD_CMD_PLAY:\r
+ DBG("rccd:RCCD_CMD_PLAY - : NOT SUPPORTED");\r
+ break;\r
+\r
+ case RCCD_CMD_CAPTURE:\r
+ DBG("rccd:RCCD_CMD_CAPTURE - : NOT SUPPORTED");\r
+ break;\r
+\r
+ case RCCD_CMD_START:\r
+ DBG("rccd:RCCD_CMD_START - : NOT SUPPORTED");\r
+ break;\r
+\r
+ case RCCD_CMD_STOP:\r
+ DBG("rccd:RCCD_CMD_STOP - : NOT SUPPORTED");\r
+ break;\r
+ case RCCD_CMD_MGET:\r
+ DBG("rccd:RCCD_CMD_MGET - : NOT SUPPORTED");\r
+ break;\r
+\r
+ case RCCD_CMD_MSET:\r
+ DBG("rccd:RCCD_CMD_MSET - : NOT SUPPORTED");\r
+ break;\r
+\r
+ case RCCD_CMD_NCTLS:\r
+ DBG("rccd:RCCD_CMD_NCTLS - : NOT SUPPORTED");\r
+ break;\r
+\r
+ case RCCD_CMD_CTL:\r
+ DBG("rccd:RCCD_CMD_CTL - : NOT SUPPORTED");\r
+ break;\r
+\r
+ case RCCD_CMD_FWID:\r
+ {\r
+ DBG("rccd:RCCD_CMD_FWID");\r
+ //u32 addr = (cmd->data[1] << 8) | (cmd->data[2]);\r
+ strcpy((char *)(cmd->data + 3), pc->fwid);\r
+ }\r
+ break;\r
+ case RCCD_CMD_SLAVE:\r
+ {\r
+ u8 slave = cmd->data[0];\r
+ int client = slave;\r
+ ioctl(pc->fCtrl, _IOW(0xE0, 5, int), &client);\r
+ DBG("Setting slave : 0x%x", slave);\r
+ }\r
+ break;\r
+ default:\r
+ DBGW("HandleI2CCmd: unsupported command: %d",\r
+ cmd->cid);\r
+ }\r
+ DBG("Getting out of rccd_cmd");\r
+ return len;\r
+}\r
+\r
+void dump_pkt(u8 *b, int nLength)\r
+{\r
+ int i;\r
+ DBG("Packet[length=%d]", nLength);\r
+ for (i = 0; i < nLength; i += 8) {\r
+ switch (nLength - i) {\r
+ case 1: DBG(" 0x%02x", b[i + 0]); break;\r
+ case 2: DBG(" 0x%02x 0x%02x", b[i + 0], b[i + 1]); break;\r
+ case 3: DBG(" 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2]); break;\r
+ case 4: DBG(" 0x%02x 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2], b[i + 3]); break;\r
+ 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;\r
+ 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;\r
+ 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;\r
+ 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;\r
+ }\r
+ }\r
+}\r
+\r
+void write_pkt(u8 *b, int nLength, char *filePath)\r
+{\r
+ int i;\r
+ int output_fd, ret_out;\r
+ char buffer[512];\r
+\r
+ output_fd = open(filePath, O_RDWR | O_APPEND | O_CREAT, 0644);\r
+\r
+ sprintf(buffer, "Packet[length=%d]%c", nLength,'\0');\r
+ ret_out = write(output_fd, &buffer, strlen(buffer));\r
+ for (i = 0; i < nLength; i += 8) {\r
+ switch (nLength - i) {\r
+ case 1: sprintf(buffer, " 0x%02x%c", b[i + 0],'\0'); break;\r
+ case 2: sprintf(buffer, " 0x%02x 0x%02x%c", b[i + 0], b[i + 1],'\0'); break;\r
+ case 3: sprintf(buffer, " 0x%02x 0x%02x 0x%02x%c", b[i + 0], b[i + 1], b[i + 2],'\0'); break;\r
+ 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;\r
+ 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;\r
+ 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;\r
+ 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;\r
+ 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;\r
+ }\r
+ ret_out = write(output_fd, &buffer, strlen(buffer));\r
+ }\r
+ sprintf(buffer, "\n%c",'\0');\r
+ ret_out = write(output_fd, &buffer, strlen(buffer));\r
+ close(output_fd);\r
+}\r
+\r
+static int get_packet(struct rccd_hdl *pc, u8 *p, int max, int *is_ping)\r
+{\r
+ int ret;\r
+ int sock = pc->clientsock;\r
+ if ((ret = recv(sock, p, max, 0)) <= 0)\r
+ goto err;\r
+ struct rccd_request *preq = (void *)p;\r
+ ++pc->pcounter;\r
+ DBG("[%8d] Received PKT %d bytes", pc->pcounter, ret);\r
+ dump_pkt(p, ret);\r
+ write_pkt(p, ret, "/sdcard/RCCD2/bytes.txt");\r
+ if (preq->target != TARGET_I2C)\r
+ DBGF("Unsupported Target ID: %d\n", preq->target);\r
+ if (preq->len < 8) {\r
+ DBGW("Packet too short");\r
+ goto err;\r
+ }\r
+\r
+ DBG("MAGIC %s", preq->magic);\r
+ if (!memcmp(preq->magic, RCCD_PING, sizeof(preq->magic)))\r
+ {\r
+ DBG("PING... ");\r
+ *is_ping = 1;\r
+ return ret;\r
+ }\r
+\r
+ if (memcmp(preq->magic, RCCD_MAGIC, sizeof(preq->magic))) {\r
+ DBGW("Incorrect signature: %c%c%c%c", preq->magic[0],\r
+ preq->magic[1], preq->magic[2], preq->magic[3]);\r
+ goto err;\r
+ }\r
+ if (!(preq->cmd[0].cid&RCCD_CMD_BLOCK) &&\r
+ (ret != (int)(preq->len + strlen(RCCD_MAGIC)))) {\r
+ DBGW("Incorrect total length: %d,%d for cid=%02x", preq->len, ret, preq->cmd[0].cid);\r
+ goto err;\r
+ }\r
+\r
+ if (preq->cmd[0].cid < RCCD_CMD_BLOCK)\r
+ return ret;\r
+\r
+ int sz = sizeof(struct rccd_request);\r
+ DBG("[%d] rccd_request size = %d\n", pc->pcounter,sz);\r
+ struct rccd_cmd_alsa *a = (void *)(preq->cmd);\r
+ struct cfw_block *b = (void *)(preq->cmd[0].data);\r
+ switch (preq->cmd[0].cid) {\r
+ case RCCD_CMD_BLOCK:\r
+ sz += sizeof(struct rccd_cmd) + CFW_BLOCK_SIZE(b->ncmds);\r
+ DBG("[%d] cid = RCCD_CMD_BLOCK size = %d\n", pc->pcounter,sz);\r
+ break;\r
+ case RCCD_CMD_OPEN:\r
+ case RCCD_CMD_CLOSE:\r
+ case RCCD_CMD_START:\r
+ case RCCD_CMD_STOP:\r
+ case RCCD_CMD_CAPTURE:\r
+ sz += sizeof(struct rccd_cmd_alsa);\r
+ DBG("[%d] cid = RCCD_CMD_CAPTURE size = %d\n", pc->pcounter,sz);\r
+ break;\r
+ case RCCD_CMD_PLAY:\r
+ sz += sizeof(struct rccd_cmd_alsa) + a->buffer_size;\r
+ DBG("[%d] cid = RCCD_CMD_PLAY size = %d\n", pc->pcounter,sz);\r
+ break;\r
+ case RCCD_CMD_MGET:\r
+ case RCCD_CMD_MSET:\r
+ case RCCD_CMD_NCTLS:\r
+ case RCCD_CMD_CTL:\r
+ sz += sizeof(struct rccd_cmd_alsa) + 256 * 2;\r
+ DBG("[%d] cid = RCCD_CMD_MGET size = %d\n", pc->pcounter,sz);\r
+ break;\r
+ default:\r
+ DBGW("Unknown command cid=%02x", preq->cmd[0].cid);\r
+ goto err;\r
+ }\r
+ if (sz > max)\r
+ goto err;\r
+ p += ret;\r
+ DBG("[%d] Got %d out of %d bytes", pc->pcounter, ret, sz);\r
+ \r
+#if 0 \r
+ while (ret < sz) {\r
+ DBG("\t%d bytes left", sz - ret);\r
+ int rsz;\r
+ if ((rsz = recv(sock, p, sz - ret, 0)) <= 0)\r
+ goto err;\r
+ ret += rsz;\r
+ }\r
+#endif \r
+ return ret;\r
+err:\r
+ if (ret < 0)\r
+ return ret;\r
+ return 0;\r
+}\r
+\r
+void *handle_client(void *p)\r
+{\r
+ struct rccd_hdl *pc = p;\r
+ int sock = pc->clientsock;\r
+ u8 *buffer = pc->buffer;\r
+ int n;\r
+\r
+ DBGI("Client thread started");\r
+ int is_ping = 0;\r
+\r
+ /* Receive message */\r
+ while ((n = get_packet(pc, buffer, RCCD_MAX_PACKET, &is_ping)) > 0)\r
+ {\r
+\r
+ struct rccd_request *preq = (void *)buffer;\r
+ int off = offsetof(struct rccd_request, cmd);\r
+ if (is_ping == 0){\r
+ DBGI("Processing Packet");\r
+\r
+ int c = rccd_cmd(pc, (struct rccd_cmd *)(buffer + off), n - off);\r
+ send(sock, buffer, off + c, 0);\r
+ }\r
+ else\r
+ {\r
+ DBGI("Pinging ..");\r
+ int len = sizeof(preq->magic);\r
+ struct rccd_cmd *cmd = (struct rccd_cmd *)(buffer + off);\r
+ memcpy(&(cmd->data[1]), preq->magic, len);\r
+ send(sock, buffer, off + len, 0);\r
+ }\r
+ is_ping = 0;\r
+ }\r
+ close(sock);\r
+\r
+ DBGI("Client disconnected");\r
+ \r
+ free(pc);\r
+ return NULL;\r
+}\r
+\r
+void sig_exit(int sig)\r
+{\r
+ DBGW("SIGTERM received. Exiting.0x%x",sig);\r
+ exit(0);\r
+}\r
+\r
+void daemonize(char *const argv[])\r
+{\r
+ int i, err, pid;\r
+ DBGI("%s", argv[0]);\r
+ if (getppid() == 1) {\r
+ DBGI("RCCD2 running in background (PID %d)", getpid());\r
+ /* already a daemon */\r
+ return;\r
+ }\r
+ for (;;) {\r
+ if ((pid = fork()) < 0)\r
+ DBGF("Fork error");\r
+ if (pid <= 0)\r
+ break;\r
+ // Parent\r
+ sleep(1);\r
+ if ((err = waitpid(pid, NULL, WNOHANG)) == 0) {\r
+ DBGW("Parent: Fork successful. Exiting");\r
+ exit(0);\r
+ }\r
+ if (err < 0) {\r
+ DBGF("Unknown error");\r
+ }\r
+\r
+ DBGW("Android killed my baby! Baby's ID = %d",pid);\r
+ }\r
+ if (setsid() < 0)\r
+ error("Unable to daemonize");\r
+ DBGI("Child running %d", getpid());\r
+ setsid();\r
+ DBGI("setsid done");\r
+ /* close standard I/O */\r
+ for (i = 0; i <= 2; ++i)\r
+ close(i);\r
+ if (0 != open("/dev/null", O_RDWR))\r
+ DBGF("Unexpected error");\r
+ dup(0); dup(0);\r
+ DBG("Closed all descriptors");\r
+\r
+\r
+ signal(SIGCHLD, SIG_IGN);\r
+ signal(SIGTSTP, SIG_IGN);\r
+ signal(SIGTTOU, SIG_IGN);\r
+ signal(SIGTTIN, SIG_IGN);\r
+ signal(SIGHUP, SIG_IGN);\r
+ /* catch kill signal */\r
+ signal(SIGTERM, sig_exit);\r
+}\r
+\r
+int read_pid(char *dname)\r
+{\r
+ int ret;\r
+ char *e, *b = strrchr(dname, '/');\r
+ if (b)\r
+ b++;\r
+ else\r
+ b = dname;\r
+ ret = strtol(b, &e, 10);\r
+ if (*e)\r
+ return -1;\r
+ return ret;\r
+}\r
+\r
+int find_server(void)\r
+{\r
+ DIR *fd;\r
+ struct dirent *fdf;\r
+ static int found = 0;\r
+ int pid;\r
+ char ln[64];\r
+ FILE *fp;\r
+\r
+ if (!(fd = opendir("/proc")))\r
+ error("Unable to open /proc");\r
+ while ((fdf = readdir(fd))) {\r
+ if ((pid = read_pid(fdf->d_name)) < 0)\r
+ continue;\r
+ if (pid == getpid())\r
+ continue;\r
+ sprintf(ln, "/proc/%d/cmdline", pid);\r
+ if (!(fp = fopen(ln, "rb")))\r
+ continue;\r
+ if (!fgets(ln, sizeof(ln), fp)) {\r
+ fclose(fp);\r
+ continue;\r
+ }\r
+ if (strstr(ln, "rccd2")) {\r
+ DBGW("Found rccd process with pid %d", pid);\r
+ ++found;\r
+ return pid;\r
+ }\r
+ }\r
+ closedir(fd);\r
+ DBGI("No %srunning rccd2 processes found", found ? "more " : "");\r
+ return 0;\r
+}\r
+\r
+void kill_server(void)\r
+{\r
+ int pid;\r
+\r
+ while ((pid = find_server())) {\r
+ DBGW("Killing rccd process with pid %d", pid);\r
+ kill(pid, SIGTERM);\r
+ }\r
+ exit(0);\r
+}\r
+\r
+const struct option options[] = {\r
+ { "help", 0, 0, 'h' },\r
+ { "verbose", 1, 0, 'v' },\r
+ { "device", 1, 0, 'd' },\r
+ { "codec-device", 0, 0, 'c' },\r
+ { "port", 1, 0, 'p' },\r
+ { "kill-server", 0, 0, 'k' },\r
+ { "safe-mode", 0, 0, 's' },\r
+ { "super-safe", 0, 0, 'S' },\r
+ { "dump", 0, 0, 'D' },\r
+ { 0, 0, 0, 0 }\r
+};\r
+\r
+void usage(int ret)\r
+{\r
+ FILE *f = stdout;\r
+ if (ret)\r
+ f = stderr;\r
+ fprintf(f,\r
+ "Usage: rccd2 [OPTIONS]\n"\r
+ " Start the Remote CodecControl Server Daemon\n"\r
+ "Options:\n"\r
+ " --help, -h Print this help\n"\r
+ " --verbose=N, -v N Set verbose level\n"\r
+ " --safe-mode, -s Use safe mode (do not fork())\n"\r
+ " --super-safe, -S Play super safe.\n"\r
+ " No fork(), no concurrent connections\n"\r
+ " --port=N, -p N Port number on which to listen\n"\r
+ " (Default: %d)\n"\r
+ " --kill-server, -k Kill any running instance of rccd2\n"\r
+ " --dump, -D Provide a log of commands as they are executed.\n"\r
+ " --device=<dev> Open <dev> as the device node\n"\r
+ " -d <dev>\n"\r
+ " --fwid=<id>, -f <id> Set firmware id\n"\r
+ " (Default: \"%s\")\n"\r
+ "\n"\r
+ " [See \"acxrun -h\" for additional help on \"--device\" and]\n"\r
+ " [\"--codec-device\" options. ]\n",\r
+ DEFAULT_PORT, DEFAULT_FWID);\r
+ exit(ret);\r
+}\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+ int serversock, clientsock;\r
+ struct sockaddr_in echoserver, echoclient;\r
+ int fCtrl, i = 0, opt, safe = 0, card = 0;\r
+ int port = DEFAULT_PORT;\r
+ char *device = NULL, *fwid = DEFAULT_FWID;\r
+ char *opts = make_opts(options);\r
+ pthread_mutex_t *mutex = ALLOC(sizeof(pthread_mutex_t));\r
+ pthread_mutex_init(mutex, NULL);\r
+\r
+ DBGI("[DMSG] %s pid=%d ppid=%d", argv[0], getpid(), getppid());\r
+ while ((opt = getopt_long(argc, argv, opts, options, &i)) != -1) {\r
+ switch (opt) {\r
+ case 'h':\r
+ usage(0);\r
+ break;\r
+ case 'v':\r
+ verbose = atoi(optarg);\r
+ break;\r
+ case 'd':\r
+ device = strdup(optarg);\r
+ break;\r
+ case 'p':\r
+ port = atoi(optarg);\r
+ break;\r
+ case 'k':\r
+ kill_server();\r
+ break;\r
+ case 's':\r
+ safe = 1;\r
+ break;\r
+ case 'D':\r
+ dump_cmds = 1;\r
+ break;\r
+ case 'S':\r
+ safe = 2;\r
+ break;\r
+ case 'r':\r
+ card = atoi(optarg);\r
+ break;\r
+ case 'f':\r
+ fwid = strdup(optarg);\r
+ break;\r
+ default:\r
+ usage(1);\r
+ }\r
+ }\r
+ while (optind < argc)\r
+ DBGW("Extra command line argument \"%s\". Ignored", argv[optind++]);\r
+ \r
+ if (getppid() != 1 && (i = find_server()))\r
+ DBGF("RCCD2 is already running (pid %d)", i);\r
+\r
+ if (!safe) {\r
+ daemonize(argv);\r
+ DBG("Running as daemon");\r
+ }\r
+\r
+ DBGW("Opening Device");\r
+ //vishnu\r
+ fCtrl = open_device(device);\r
+ \r
+ /* Create the TCP socket */\r
+ if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)\r
+ DBGF("Failed to create socket");\r
+ /* Construct the server sockaddr_in structure */\r
+ /* Clear struct */\r
+ memset(&echoserver, 0, sizeof(echoserver));\r
+ /* Internet/IP */\r
+ echoserver.sin_family = AF_INET;\r
+ /* Incoming addr */\r
+ echoserver.sin_addr.s_addr = htonl(INADDR_ANY);\r
+ /* server port */\r
+ echoserver.sin_port = htons(port);\r
+\r
+ /* Bind the server socket */\r
+ DBGW("Bind Server Socket");\r
+ if (bind(serversock, (struct sockaddr *)&echoserver, sizeof(echoserver)) < 0)\r
+ DBGF("Failed to bind the server socket");\r
+\r
+ /* Listen on the server socket */\r
+ if (listen(serversock, MAXPENDING) < 0)\r
+ DBGF("Failed to listen on server socket");\r
+\r
+ /* Run until cancelled */\r
+ while (1) {\r
+ socklen_t clientlen = sizeof(echoclient);\r
+ DBGI("Waiting for client connection...");\r
+ /* Wait for client connection */\r
+ if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient,\r
+ &clientlen)) < 0)\r
+ DBGF("Failed to accept client connection");\r
+ DBGI("Client connected: %s", inet_ntoa(echoclient.sin_addr));\r
+ struct rccd_hdl *p = ALLOC(sizeof(struct rccd_hdl) + sizeof(union cfw_cmd)*BUFFSIZE);\r
+ pthread_t tid;\r
+ strcpy(p->fwid, fwid);\r
+ p->clientsock = clientsock;\r
+ p->fCtrl = fCtrl;\r
+ p->mutex = mutex;\r
+ /* Pass mutex as well */ \r
+ if (safe > 1)\r
+ {\r
+ DBG("Entering Safe Mode");\r
+ handle_client(p);\r
+ }\r
+ else\r
+ {\r
+ DBG("Starting in thread");\r
+\r
+ if (pthread_create(&tid, NULL, handle_client, p) != 0)\r
+ DBGF("Error creating thread");\r
+ }\r
+ }\r
+}\r
diff --git a/rccd2/rccd2.sh b/rccd2/rccd2.sh
--- /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
--- /dev/null
+++ b/rccd2/utils.c
@@ -0,0 +1,79 @@
+#define _GNU_SOURCE
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+
+#include "utils.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+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 f1638c9de3e5fc94c1137cbb623da2ae783815c9..6597f47d903219169231aca4fa91abbc60a4127c 100755 (executable)
rename from Android.mk
rename to ti_audio/Android.mk
index f1638c9de3e5fc94c1137cbb623da2ae783815c9..6597f47d903219169231aca4fa91abbc60a4127c 100755 (executable)
--- a/Android.mk
+++ b/ti_audio/Android.mk
LOCAL_SRC_FILES := main.c
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_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
LOCAL_MODULE_TAGS := debug
LOCAL_SYSTEM_SHARED_LIBRARIES := libc libm
diff --git a/CleanSpec.mk b/ti_audio/CleanSpec.mk
diff --git a/main.c b/ti_audio/main.c
diff --git a/ti_audio.h b/ti_audio/ti_audio.h