add rccd2 for PPC3 TAS2557 app end-system integration
[tas2557sw-android/tas2557-stereo-util.git] / rccd2 / rccd2.c
1 #include <stdio.h>\r
2 #include <stddef.h>\r
3 #include <string.h>\r
4 #include <sys/types.h>\r
5 #include <sys/stat.h>\r
6 #include <sys/wait.h>\r
7 #include <dirent.h>\r
8 #include <pthread.h>\r
9 #include <sys/socket.h>\r
10 #include <sys/ioctl.h>\r
11 #include <arpa/inet.h>\r
12 #include <stdlib.h>\r
13 #include <string.h>\r
14 #include <unistd.h>\r
15 #include <signal.h>\r
16 #include <netinet/in.h>\r
17 #include <fcntl.h>\r
18 #include <time.h>\r
19 #include <getopt.h>\r
20 #include "utils.h"\r
21 #include "android_utils.h"\r
22 #include "rccd2.h"\r
23 #include "aic3xxx_cfw.h"\r
24 \r
25 /* Max connection requests */\r
26 #define MAXPENDING      (16)\r
27 #define BUFFSIZE        (256)\r
28 #define DEFAULT_PORT    (80)\r
29 \r
30 /* State of each independent connection */\r
31 struct rccd_hdl {\r
32         u32 pcounter;\r
33         char fwid[32];\r
34         int clientsock;\r
35         int fCtrl;\r
36         pthread_mutex_t *mutex;\r
37         int slave_id,book, page;\r
38         u8 buffer[RCCD_MAX_PACKET];\r
39         struct cfw_block block;\r
40 };\r
41 \r
42 #define CRITICAL(code_section__) do {           \\r
43 if (pthread_mutex_lock(pc->mutex))          \\r
44         DBGF("Error obtaining mutex lock");     \\r
45         \\r
46         code_section__;                             \\r
47         \\r
48 if (pthread_mutex_unlock(pc->mutex))        \\r
49         DBGF("Error releasing mutex lock");     \\r
50 } while (0)\r
51 \r
52 void legacy_read(struct rccd_hdl *pc, u8 *buf, int n)\r
53 {\r
54         pc->block.ncmds = CFW_CMD_BURST_LEN(n);\r
55         pc->block.cmd[0].bhdr.cid = CFW_CMD_RBURST;\r
56         pc->block.cmd[0].bhdr.len = n;\r
57         //pc->block.cmd[1].burst.slave_id = pc->slave_id;\r
58         pc->block.cmd[1].burst.book = pc->book;\r
59         pc->block.cmd[1].burst.page = pc->page;\r
60         pc->block.cmd[1].burst.offset = buf[0];\r
61         DBG("legacy_read: (%d,%d,%d) %d bytes", pc->book, pc->page, buf[0], n);\r
62         CRITICAL(run_block(&(pc->block), NULL));\r
63         memcpy(buf + 1, pc->block.cmd[1].burst.data, n);\r
64 }\r
65 \r
66 void legacy_write(struct rccd_hdl *pc, u8 *buf, int n)\r
67 {\r
68         u8 *pd = buf;\r
69         if (buf[0] == 127) {\r
70                 pc->book = buf[1];\r
71                 if (n != 2)\r
72                         DBGW("Received book change as part of burst command.  "\r
73                         "Additional writes have been ignored (n=%d)", n);\r
74                 return;\r
75         }\r
76         if (buf[0] == 0) {\r
77                 pc->page = buf[1];\r
78                 --n;\r
79                 if (n <= 1)\r
80                         return;\r
81                 ++pd;\r
82                 pd[0] = 1;\r
83         }\r
84         pc->block.ncmds = CFW_CMD_BURST_LEN(n - 1);\r
85         pc->block.cmd[0].bhdr.cid = CFW_CMD_BURST;\r
86         pc->block.cmd[0].bhdr.len = n - 1;\r
87         //pc->block.cmd[1].burst.slave_id = pc->slave_id;\r
88         pc->block.cmd[1].burst.book = pc->book;\r
89         pc->block.cmd[1].burst.page = pc->page;\r
90         pc->block.cmd[1].burst.offset = pd[0];\r
91         memcpy(pc->block.cmd[1].burst.data, &pd[1], n - 1);\r
92         DBG("legacy_write: (%d,%d,%d) %d bytes", pc->book, pc->page, pd[0], n - 1);\r
93         CRITICAL(run_block(&(pc->block), NULL));\r
94 }\r
95 \r
96 int rccd_cmd(struct rccd_hdl *pc, struct rccd_cmd *cmd, int len)\r
97 {\r
98         DBG("Getting into rccd_cmd");\r
99         const char * const cid_str[] = {\r
100                 [RCCD_CMD_READ] = "RCCD_CMD_READ",\r
101                 [RCCD_CMD_WRITE] = "RCCD_CMD_WRITE",\r
102                 [RCCD_CMD_SLAVE] = "RCCD_CMD_SLAVE",\r
103                 [RCCD_CMD_FWID] = "RCCD_CMD_FWID",\r
104                 [RCCD_CMD_BLOCK] = "RCCD_CMD_BLOCK",\r
105                 [RCCD_CMD_OPEN] = "RCCD_CMD_OPEN",\r
106                 [RCCD_CMD_CLOSE] = "RCCD_CMD_CLOSE",\r
107                 [RCCD_CMD_PLAY] = "RCCD_CMD_PLAY",\r
108                 [RCCD_CMD_CAPTURE] = "RCCD_CMD_CAPTURE",\r
109                 [RCCD_CMD_START] = "RCCD_CMD_START",\r
110                 [RCCD_CMD_STOP] = "RCCD_CMD_STOP",\r
111                 [RCCD_CMD_MGET] = "RCCD_CMD_MGET",\r
112                 [RCCD_CMD_MSET] = "RCCD_CMD_MSET",\r
113                 [RCCD_CMD_NCTLS] = "RCCD_CMD_NCTLS",\r
114                 [RCCD_CMD_CTL] = "RCCD_CMD_CTL",\r
115         };\r
116 \r
117         DBG("%s: cid=%0x \"%s\"  len=%d", __FUNCTION__, cmd->cid, cid_str[cmd->cid],\r
118                 cmd->len);\r
119 \r
120         //if (!pc->mixer && cmd->cid > RCCD_CMD_BLOCK)\r
121         //      DBGF("Attempt to do ALSA operation when no sound card is present");\r
122 \r
123         switch (cmd->cid) {\r
124         case RCCD_CMD_READ:\r
125                 DBG("rccd:RCCD_CMD_READ");\r
126                 if (cmd->len < 4)\r
127                         break;\r
128                 legacy_read(pc, cmd->data, cmd->len - 4);\r
129                 break;\r
130         case RCCD_CMD_WRITE:\r
131                 DBG("rccd:RCCD_CMD_WRITE");\r
132                 if (cmd->len < 4)\r
133                         break;\r
134                 legacy_write(pc, cmd->data, cmd->len - 4 + 1);\r
135                 break;\r
136         case RCCD_CMD_BLOCK:\r
137         {\r
138                 DBG("rccd:RCCD_CMD_BLOCK");\r
139                 u8 var[256];\r
140                 struct cfw_block *b = (void *)cmd->data;\r
141                 len = CFW_BLOCK_SIZE(b->ncmds) + sizeof(struct rccd_cmd);\r
142                 CRITICAL(run_block(b, var));\r
143         }\r
144                 break;\r
145         case RCCD_CMD_OPEN:\r
146                 DBG("rccd:RCCD_CMD_OPEN - : NOT SUPPORTED");\r
147                 break;\r
148         case RCCD_CMD_CLOSE:\r
149                 DBG("rccd:RCCD_CMD_CLOSE - : NOT SUPPORTED");\r
150                 break;\r
151         case RCCD_CMD_PLAY:\r
152                 DBG("rccd:RCCD_CMD_PLAY - : NOT SUPPORTED");\r
153                 break;\r
154 \r
155         case RCCD_CMD_CAPTURE:\r
156                 DBG("rccd:RCCD_CMD_CAPTURE - : NOT SUPPORTED");\r
157                 break;\r
158 \r
159         case RCCD_CMD_START:\r
160                 DBG("rccd:RCCD_CMD_START - : NOT SUPPORTED");\r
161                 break;\r
162 \r
163         case RCCD_CMD_STOP:\r
164                 DBG("rccd:RCCD_CMD_STOP - : NOT SUPPORTED");\r
165                 break;\r
166         case RCCD_CMD_MGET:\r
167                 DBG("rccd:RCCD_CMD_MGET - : NOT SUPPORTED");\r
168                 break;\r
169 \r
170         case RCCD_CMD_MSET:\r
171                 DBG("rccd:RCCD_CMD_MSET - : NOT SUPPORTED");\r
172                 break;\r
173 \r
174         case RCCD_CMD_NCTLS:\r
175                 DBG("rccd:RCCD_CMD_NCTLS - : NOT SUPPORTED");\r
176                 break;\r
177 \r
178         case RCCD_CMD_CTL:\r
179                 DBG("rccd:RCCD_CMD_CTL - : NOT SUPPORTED");\r
180                 break;\r
181 \r
182         case RCCD_CMD_FWID:\r
183         {\r
184                 DBG("rccd:RCCD_CMD_FWID");\r
185                 //u32 addr = (cmd->data[1] << 8) | (cmd->data[2]);\r
186                 strcpy((char *)(cmd->data + 3), pc->fwid);\r
187         }\r
188                 break;\r
189         case RCCD_CMD_SLAVE:\r
190         {\r
191                 u8 slave = cmd->data[0];\r
192                 int client = slave;\r
193                 ioctl(pc->fCtrl, _IOW(0xE0, 5, int), &client);\r
194                 DBG("Setting slave : 0x%x", slave);\r
195         }\r
196                 break;\r
197         default:\r
198                 DBGW("HandleI2CCmd: unsupported command: %d",\r
199                         cmd->cid);\r
200         }\r
201         DBG("Getting out of rccd_cmd");\r
202         return len;\r
203 }\r
204 \r
205 void dump_pkt(u8 *b, int nLength)\r
206 {\r
207         int i;\r
208         DBG("Packet[length=%d]", nLength);\r
209         for (i = 0; i < nLength; i += 8) {\r
210                 switch (nLength - i) {\r
211                 case 1: DBG(" 0x%02x", b[i + 0]); break;\r
212                 case 2: DBG(" 0x%02x 0x%02x", b[i + 0], b[i + 1]); break;\r
213                 case 3: DBG(" 0x%02x 0x%02x 0x%02x", b[i + 0], b[i + 1], b[i + 2]); break;\r
214                 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
215                 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
216                 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
217                 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
218                 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
219                 }\r
220         }\r
221 }\r
222 \r
223 void write_pkt(u8 *b, int nLength, char *filePath)\r
224 {\r
225         int i;\r
226         int output_fd, ret_out;\r
227         char buffer[512];\r
228 \r
229         output_fd = open(filePath, O_RDWR | O_APPEND | O_CREAT, 0644);\r
230 \r
231         sprintf(buffer, "Packet[length=%d]%c", nLength,'\0');\r
232         ret_out = write(output_fd, &buffer, strlen(buffer));\r
233         for (i = 0; i < nLength; i += 8) {\r
234                 switch (nLength - i) {\r
235                 case 1: sprintf(buffer, " 0x%02x%c", b[i + 0],'\0'); break;\r
236                 case 2: sprintf(buffer, " 0x%02x 0x%02x%c", b[i + 0], b[i + 1],'\0'); break;\r
237                 case 3: sprintf(buffer, " 0x%02x 0x%02x 0x%02x%c", b[i + 0], b[i + 1], b[i + 2],'\0'); break;\r
238                 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
239                 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
240                 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
241                 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
242                 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
243                 }\r
244                 ret_out = write(output_fd, &buffer, strlen(buffer));\r
245         }\r
246         sprintf(buffer, "\n%c",'\0');\r
247         ret_out = write(output_fd, &buffer, strlen(buffer));\r
248         close(output_fd);\r
249 }\r
250 \r
251 static int get_packet(struct rccd_hdl *pc, u8 *p, int max, int *is_ping)\r
252 {\r
253         int ret;\r
254         int sock = pc->clientsock;\r
255         if ((ret = recv(sock, p, max, 0)) <= 0)\r
256                 goto err;\r
257         struct rccd_request *preq = (void *)p;\r
258         ++pc->pcounter;\r
259         DBG("[%8d] Received PKT %d bytes", pc->pcounter, ret);\r
260         dump_pkt(p, ret);\r
261         write_pkt(p, ret, "/sdcard/RCCD2/bytes.txt");\r
262         if (preq->target != TARGET_I2C)\r
263                 DBGF("Unsupported Target ID: %d\n", preq->target);\r
264         if (preq->len < 8) {\r
265                 DBGW("Packet too short");\r
266                 goto err;\r
267         }\r
268 \r
269         DBG("MAGIC %s", preq->magic);\r
270         if (!memcmp(preq->magic, RCCD_PING, sizeof(preq->magic)))\r
271         {\r
272                 DBG("PING... ");\r
273                 *is_ping = 1;\r
274                 return ret;\r
275         }\r
276 \r
277         if (memcmp(preq->magic, RCCD_MAGIC, sizeof(preq->magic))) {\r
278                 DBGW("Incorrect signature: %c%c%c%c", preq->magic[0],\r
279                         preq->magic[1], preq->magic[2], preq->magic[3]);\r
280                 goto err;\r
281         }\r
282         if (!(preq->cmd[0].cid&RCCD_CMD_BLOCK) &&\r
283                 (ret != (int)(preq->len + strlen(RCCD_MAGIC)))) {\r
284                 DBGW("Incorrect total length: %d,%d for cid=%02x", preq->len, ret, preq->cmd[0].cid);\r
285                 goto err;\r
286         }\r
287 \r
288         if (preq->cmd[0].cid < RCCD_CMD_BLOCK)\r
289                 return ret;\r
290 \r
291         int sz = sizeof(struct rccd_request);\r
292         DBG("[%d] rccd_request size = %d\n", pc->pcounter,sz);\r
293         struct rccd_cmd_alsa *a = (void *)(preq->cmd);\r
294         struct cfw_block *b = (void *)(preq->cmd[0].data);\r
295         switch (preq->cmd[0].cid) {\r
296         case RCCD_CMD_BLOCK:\r
297                 sz += sizeof(struct rccd_cmd) + CFW_BLOCK_SIZE(b->ncmds);\r
298                 DBG("[%d] cid = RCCD_CMD_BLOCK size = %d\n", pc->pcounter,sz);\r
299                 break;\r
300         case RCCD_CMD_OPEN:\r
301         case RCCD_CMD_CLOSE:\r
302         case RCCD_CMD_START:\r
303         case RCCD_CMD_STOP:\r
304         case RCCD_CMD_CAPTURE:\r
305                 sz += sizeof(struct rccd_cmd_alsa);\r
306                 DBG("[%d] cid = RCCD_CMD_CAPTURE size = %d\n", pc->pcounter,sz);\r
307                 break;\r
308         case RCCD_CMD_PLAY:\r
309                 sz += sizeof(struct rccd_cmd_alsa) + a->buffer_size;\r
310                 DBG("[%d] cid = RCCD_CMD_PLAY size = %d\n", pc->pcounter,sz);\r
311                 break;\r
312         case RCCD_CMD_MGET:\r
313         case RCCD_CMD_MSET:\r
314         case RCCD_CMD_NCTLS:\r
315         case RCCD_CMD_CTL:\r
316                 sz += sizeof(struct rccd_cmd_alsa) + 256 * 2;\r
317                 DBG("[%d] cid = RCCD_CMD_MGET size = %d\n", pc->pcounter,sz);\r
318                 break;\r
319         default:\r
320                 DBGW("Unknown command cid=%02x", preq->cmd[0].cid);\r
321                 goto err;\r
322         }\r
323         if (sz > max)\r
324                 goto err;\r
325         p += ret;\r
326         DBG("[%d] Got %d out of %d bytes", pc->pcounter, ret, sz);\r
327         \r
328 #if 0   \r
329         while (ret < sz) {\r
330                 DBG("\t%d bytes left", sz - ret);\r
331                 int rsz;\r
332                 if ((rsz = recv(sock, p, sz - ret, 0)) <= 0)\r
333                         goto err;\r
334                 ret += rsz;\r
335         }\r
336 #endif  \r
337         return ret;\r
338 err:\r
339         if (ret < 0)\r
340                 return ret;\r
341         return 0;\r
342 }\r
343 \r
344 void *handle_client(void *p)\r
345 {\r
346         struct rccd_hdl *pc = p;\r
347         int sock = pc->clientsock;\r
348         u8 *buffer = pc->buffer;\r
349         int n;\r
350 \r
351         DBGI("Client thread started");\r
352         int is_ping = 0;\r
353 \r
354         /* Receive message */\r
355         while ((n = get_packet(pc, buffer, RCCD_MAX_PACKET, &is_ping)) > 0)\r
356         {\r
357 \r
358                 struct rccd_request *preq = (void *)buffer;\r
359                 int off = offsetof(struct rccd_request, cmd);\r
360                 if (is_ping == 0){\r
361                         DBGI("Processing Packet");\r
362 \r
363                         int c = rccd_cmd(pc, (struct rccd_cmd *)(buffer + off), n - off);\r
364                         send(sock, buffer, off + c, 0);\r
365                 }\r
366                 else\r
367                 {\r
368                         DBGI("Pinging ..");\r
369                         int len = sizeof(preq->magic);\r
370                         struct rccd_cmd *cmd = (struct rccd_cmd *)(buffer + off);\r
371                         memcpy(&(cmd->data[1]), preq->magic, len);\r
372                         send(sock, buffer, off + len, 0);\r
373                 }\r
374                 is_ping = 0;\r
375         }\r
376         close(sock);\r
377 \r
378         DBGI("Client disconnected");\r
379         \r
380         free(pc);\r
381         return NULL;\r
382 }\r
383 \r
384 void sig_exit(int sig)\r
385 {\r
386         DBGW("SIGTERM received. Exiting.0x%x",sig);\r
387         exit(0);\r
388 }\r
389 \r
390 void daemonize(char *const argv[])\r
391 {\r
392         int i, err, pid;\r
393         DBGI("%s", argv[0]);\r
394         if (getppid() == 1) {\r
395                 DBGI("RCCD2 running in background (PID %d)", getpid());\r
396                 /* already a daemon */\r
397                 return;\r
398         }\r
399         for (;;) {\r
400                 if ((pid = fork()) < 0)\r
401                         DBGF("Fork error");\r
402                 if (pid <= 0)\r
403                         break;\r
404                 // Parent\r
405                 sleep(1);\r
406                 if ((err = waitpid(pid, NULL, WNOHANG)) == 0) {\r
407                         DBGW("Parent: Fork successful.  Exiting");\r
408                         exit(0);\r
409                 }\r
410                 if (err < 0) {\r
411                         DBGF("Unknown error");\r
412                 }\r
413 \r
414                 DBGW("Android killed my baby! Baby's ID = %d",pid);\r
415         }\r
416         if (setsid() < 0)\r
417                 error("Unable to daemonize");\r
418         DBGI("Child running %d", getpid());\r
419         setsid();\r
420         DBGI("setsid done");\r
421         /* close standard I/O */\r
422         for (i = 0; i <= 2; ++i)\r
423                 close(i);\r
424         if (0 != open("/dev/null", O_RDWR))\r
425                 DBGF("Unexpected error");\r
426         dup(0); dup(0);\r
427         DBG("Closed all descriptors");\r
428 \r
429 \r
430         signal(SIGCHLD, SIG_IGN);\r
431         signal(SIGTSTP, SIG_IGN);\r
432         signal(SIGTTOU, SIG_IGN);\r
433         signal(SIGTTIN, SIG_IGN);\r
434         signal(SIGHUP, SIG_IGN);\r
435         /* catch kill signal */\r
436         signal(SIGTERM, sig_exit);\r
437 }\r
438 \r
439 int read_pid(char *dname)\r
440 {\r
441         int ret;\r
442         char *e, *b = strrchr(dname, '/');\r
443         if (b)\r
444                 b++;\r
445         else\r
446                 b = dname;\r
447         ret = strtol(b, &e, 10);\r
448         if (*e)\r
449                 return -1;\r
450         return ret;\r
451 }\r
452 \r
453 int find_server(void)\r
454 {\r
455         DIR *fd;\r
456         struct dirent *fdf;\r
457         static int found = 0;\r
458         int  pid;\r
459         char ln[64];\r
460         FILE *fp;\r
461 \r
462         if (!(fd = opendir("/proc")))\r
463                 error("Unable to open /proc");\r
464         while ((fdf = readdir(fd))) {\r
465                 if ((pid = read_pid(fdf->d_name)) < 0)\r
466                         continue;\r
467                 if (pid == getpid())\r
468                         continue;\r
469                 sprintf(ln, "/proc/%d/cmdline", pid);\r
470                 if (!(fp = fopen(ln, "rb")))\r
471                         continue;\r
472                 if (!fgets(ln, sizeof(ln), fp)) {\r
473                         fclose(fp);\r
474                         continue;\r
475                 }\r
476                 if (strstr(ln, "rccd2")) {\r
477                         DBGW("Found rccd process with pid %d", pid);\r
478                         ++found;\r
479                         return pid;\r
480                 }\r
481         }\r
482         closedir(fd);\r
483         DBGI("No %srunning rccd2 processes found", found ? "more " : "");\r
484         return 0;\r
485 }\r
486 \r
487 void kill_server(void)\r
488 {\r
489         int pid;\r
490 \r
491         while ((pid = find_server())) {\r
492                 DBGW("Killing rccd process with pid %d", pid);\r
493                 kill(pid, SIGTERM);\r
494         }\r
495         exit(0);\r
496 }\r
497 \r
498 const struct option options[] = {\r
499         { "help", 0, 0, 'h' },\r
500         { "verbose", 1, 0, 'v' },\r
501         { "device", 1, 0, 'd' },\r
502         { "codec-device", 0, 0, 'c' },\r
503         { "port", 1, 0, 'p' },\r
504         { "kill-server", 0, 0, 'k' },\r
505         { "safe-mode", 0, 0, 's' },\r
506         { "super-safe", 0, 0, 'S' },\r
507         { "dump", 0, 0, 'D' },\r
508         { 0, 0, 0, 0 }\r
509 };\r
510 \r
511 void usage(int ret)\r
512 {\r
513         FILE *f = stdout;\r
514         if (ret)\r
515                 f = stderr;\r
516         fprintf(f,\r
517                 "Usage: rccd2 [OPTIONS]\n"\r
518                 "        Start the Remote CodecControl Server Daemon\n"\r
519                 "Options:\n"\r
520                 "    --help, -h              Print this help\n"\r
521                 "    --verbose=N, -v N       Set verbose level\n"\r
522                 "    --safe-mode, -s         Use safe mode (do not fork())\n"\r
523                 "    --super-safe, -S        Play super safe.\n"\r
524                 "                               No fork(), no concurrent connections\n"\r
525                 "    --port=N, -p N          Port number on which to listen\n"\r
526                 "                                (Default: %d)\n"\r
527                 "    --kill-server, -k       Kill any running instance of rccd2\n"\r
528                 "    --dump, -D              Provide a log of commands as they are executed.\n"\r
529                 "    --device=<dev>          Open <dev> as the device node\n"\r
530                 "        -d <dev>\n"\r
531                 "    --fwid=<id>, -f <id>    Set firmware id\n"\r
532                 "                                (Default: \"%s\")\n"\r
533                 "\n"\r
534                 "    [See \"acxrun -h\" for additional help on \"--device\" and]\n"\r
535                 "    [\"--codec-device\" options.                              ]\n",\r
536                 DEFAULT_PORT, DEFAULT_FWID);\r
537         exit(ret);\r
538 }\r
539 \r
540 int main(int argc, char *argv[])\r
541 {\r
542         int serversock, clientsock;\r
543         struct sockaddr_in echoserver, echoclient;\r
544         int fCtrl, i = 0, opt, safe = 0, card = 0;\r
545         int port = DEFAULT_PORT;\r
546         char *device = NULL, *fwid = DEFAULT_FWID;\r
547         char *opts = make_opts(options);\r
548         pthread_mutex_t *mutex = ALLOC(sizeof(pthread_mutex_t));\r
549         pthread_mutex_init(mutex, NULL);\r
550 \r
551         DBGI("[DMSG] %s pid=%d ppid=%d", argv[0], getpid(), getppid());\r
552         while ((opt = getopt_long(argc, argv, opts, options, &i)) != -1) {\r
553                 switch (opt) {\r
554                 case 'h':\r
555                         usage(0);\r
556                         break;\r
557                 case 'v':\r
558                         verbose = atoi(optarg);\r
559                         break;\r
560                 case 'd':\r
561                         device = strdup(optarg);\r
562                         break;\r
563                 case 'p':\r
564                         port = atoi(optarg);\r
565                         break;\r
566                 case 'k':\r
567                         kill_server();\r
568                         break;\r
569                 case 's':\r
570                         safe = 1;\r
571                         break;\r
572                 case 'D':\r
573                         dump_cmds = 1;\r
574                         break;\r
575                 case 'S':\r
576                         safe = 2;\r
577                         break;\r
578                 case 'r':\r
579                         card = atoi(optarg);\r
580                         break;\r
581                 case 'f':\r
582                         fwid = strdup(optarg);\r
583                         break;\r
584                 default:\r
585                         usage(1);\r
586                 }\r
587         }\r
588         while (optind < argc)\r
589                 DBGW("Extra command line argument \"%s\".  Ignored", argv[optind++]);\r
590         \r
591         if (getppid() != 1 && (i = find_server()))\r
592                 DBGF("RCCD2 is already running (pid %d)", i);\r
593 \r
594         if (!safe) {\r
595                 daemonize(argv);\r
596                 DBG("Running as daemon");\r
597         }\r
598 \r
599         DBGW("Opening Device");\r
600         //vishnu\r
601         fCtrl = open_device(device);\r
602         \r
603         /* Create the TCP socket */\r
604         if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)\r
605                 DBGF("Failed to create socket");\r
606         /* Construct the server sockaddr_in structure */\r
607         /* Clear struct */\r
608         memset(&echoserver, 0, sizeof(echoserver));\r
609         /* Internet/IP */\r
610         echoserver.sin_family = AF_INET;\r
611         /* Incoming addr */\r
612         echoserver.sin_addr.s_addr = htonl(INADDR_ANY);\r
613         /* server port */\r
614         echoserver.sin_port = htons(port);\r
615 \r
616         /* Bind the server socket */\r
617         DBGW("Bind Server Socket");\r
618         if (bind(serversock, (struct sockaddr *)&echoserver, sizeof(echoserver)) < 0)\r
619                 DBGF("Failed to bind the server socket");\r
620 \r
621         /* Listen on the server socket */\r
622         if (listen(serversock, MAXPENDING) < 0)\r
623                 DBGF("Failed to listen on server socket");\r
624 \r
625         /* Run until cancelled */\r
626         while (1) {\r
627                 socklen_t clientlen = sizeof(echoclient);\r
628                 DBGI("Waiting for client connection...");\r
629                 /* Wait for client connection */\r
630                 if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient,\r
631                         &clientlen)) < 0)\r
632                         DBGF("Failed to accept client connection");\r
633                 DBGI("Client connected: %s", inet_ntoa(echoclient.sin_addr));\r
634                 struct rccd_hdl *p = ALLOC(sizeof(struct rccd_hdl) + sizeof(union cfw_cmd)*BUFFSIZE);\r
635                 pthread_t tid;\r
636                 strcpy(p->fwid, fwid);\r
637                 p->clientsock = clientsock;\r
638                 p->fCtrl = fCtrl;\r
639                 p->mutex = mutex;\r
640                 /* Pass mutex  as well */ \r
641                 if (safe > 1)\r
642                 {\r
643                         DBG("Entering Safe Mode");\r
644                         handle_client(p);\r
645                 }\r
646                 else\r
647                 {\r
648                         DBG("Starting in thread");\r
649 \r
650                         if (pthread_create(&tid, NULL, handle_client, p) != 0)\r
651                                 DBGF("Error creating thread");\r
652                 }\r
653         }\r
654 }\r