• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010, Atmel Corporation.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above copyright
9 //       notice, this list of conditions and the following disclaimer in the
10 //       documentation and/or other materials provided with the distribution.
11 //     * Neither the name of Atmel nor the
12 //       names of its contributors may be used to endorse or promote products
13 //       derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include <signal.h>
27 #include <string.h>
28 #include <pthread.h>
29 #include <semaphore.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <fcntl.h>
33 #include <sys/ioctl.h>
34 #include <sys/socket.h>
35 #include <sys/un.h>
36 #include <sys/stat.h>
37 #include <errno.h>
38 #include <linux/netlink.h>
39 #include <cutils/properties.h>
40 #include <hardware_legacy/power.h>
41 #include <stdlib.h>
42 #include <time.h>
43 #include <linux/capability.h>
44 #include <linux/prctl.h>
45 #include <private/android_filesystem_config.h>
46 
47 #include <linux/spi/cpcap.h>
48 #include <linux/hidraw.h>
49 
50 
51 #include "SA_Phys_Linux.h"
52 #include "SHA_CommMarshalling.h"
53 #include "SHA_Status.h"
54 #include "SHA_Comm.h"
55 #include "SHA_TimeUtils.h"
56 #include "Whisper_AccyMain.h"
57 
58 
59 /*==================================================================================================
60                                           LOCAL CONSTANTS
61 ==================================================================================================*/
62 static const char xintToChar[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
63 static const char wakeLockString[] = "ACCYDET";
64 static const uint8_t hidStatusQuery[] = {0x3f, 0x30, 0x00, 0x00, 0x42, 0x99};
65 static const uint8_t hidIdQuery[] = {0x3f, 0x12, 0x00, 0x01, 0xf1, 0xe2};
66 
67 
68 /*==================================================================================================
69                                             LOCAL MACROS
70 ==================================================================================================*/
71 
72 #define MAX_TRY_WAKEUP                  4
73 #define MAX_TRY_COMM                    2
74 #define UART_SWITCH_STATE_PATH          "/sys/class/switch/whisper/state"
75 #define HID_SWITCH_STATE_PATH           "/sys/class/switch/whisper_hid/state"
76 #define DOCK_TYPE_OFFSET                27
77 
78 #define DOCK_ATTACHED                   '1'
79 #define DOCK_NOT_ATTACHED               '0'
80 
81 #define HID_SUCCESS                     1
82 #define HID_FAILURE                     0
83 
84 #define ID_SUCCESS                      1
85 
86 #define IOCTL_SUCCESS                   0
87 #define MAX_TRY_IOCTL                   5
88 
89 #define HID_STATUS_QUERY_LENGTH         64
90 #define HID_ID_QUERY_LENGTH             64
91 #define HID_MAC_QUERY_LENGTH            64
92 #define HID_STATUS_MSG_LENGTH		64
93 #define HID_ID_MSG_LENGTH		64
94 #define HID_MAC_MSG_LENGTH		64
95 
96 #define LOG_FILE_NAME                   "/data/whisper/whisperd.log"
97 #define LOG_FILE_PATH                   "/data/whisper"
98 
99 /*==================================================================================================
100                                           EXTERNAL VARIABLES
101 ==================================================================================================*/
102 
103 /*==================================================================================================
104                                      LOCAL FUNCTION PROTOTYPES
105 ==================================================================================================*/
106 static void copyResults(int8_t cmdSize, uint8_t *out);
107 static int  accyInit(void);
108 static void accySigHandler(signed int signal);
109 static void accyProtDaemon(void *arg);
110 static void readSwitchState(int);
111 static int  accySpawnThread();
112 static void createOutput(uint8_t *inp, char *out, int bytes);
113 static void waitForUevents();
114 static void doIoctl(int cmd, unsigned int data, char *dev_id, char *dev_prop);
115 
116 /*==================================================================================================
117                                           LOCAL VARIABLES
118 ==================================================================================================*/
119 static SHA_CommParameters*    mainparms;
120 static sem_t SigAccyProtStart;
121 static int ueventFd;
122 static int wakeLock = 0;
123 static int globalState;
124 static int globalProtocol;
125 static int cpcapFd = -1;
126 static int hidFd = -1;
127 
128 /*==================================================================================================
129                                           GLOBAL VARIABLES
130 ==================================================================================================*/
131 FILE *logFp = NULL;
132 int  currLogSize = 0;
133 
134 /*==================================================================================================
135                                           LOCAL FUNCTIONS
136 ==================================================================================================*/
137 
138 
readSwitchState(int protocolType)139 static void readSwitchState(int protocolType) {
140     const int SIZE = 16;
141     int switchFd = -1;
142     char buf[SIZE];
143     int count;
144 
145     if (protocolType == PROTOCOL_UART) {
146         switchFd = open(UART_SWITCH_STATE_PATH, O_RDONLY, 0);
147         if (switchFd == -1) {
148             DBG_ERROR("Failed opening %s, errno = %s", UART_SWITCH_STATE_PATH, strerror(errno));
149             return;
150         }
151     }
152     else if (protocolType == PROTOCOL_HID) {
153         switchFd = open(HID_SWITCH_STATE_PATH, O_RDONLY, 0);
154         if (switchFd == -1) {
155             DBG_ERROR("Failed opening %s, errno = %s", HID_SWITCH_STATE_PATH, strerror(errno));
156             return;
157         }
158     }
159 
160     do {
161       count = read(switchFd, buf, SIZE);
162     } while (count < 0 && errno == EINTR);
163 
164     if (count < 1) {
165         DBG_ERROR("Error reading switch, returned %d", count);
166         close(switchFd);
167         return;
168     }
169 
170     if (buf[0] == DOCK_ATTACHED) {
171         globalState = GLOBAL_STATE_DOCKED;
172         if (protocolType == PROTOCOL_HID) {
173             char hidDevice[] = "/dev/hidraw0";
174             int i;
175             struct hidraw_devinfo hiddevinfo;
176             int status;
177 
178             globalProtocol = PROTOCOL_HID;
179             DBG_TRACE("HID Dock Attached");
180 
181             for (i = 0; i < HIDRAW_MAX_DEVICES; i++) {
182                 hidFd = open(hidDevice, O_RDWR);
183 
184                 if(hidFd < 0) {
185                     DBG_ERROR("Failed to open HID Device:%s", hidDevice);
186                     break;
187                 }
188                 else {
189                     status = ioctl(hidFd, HIDIOCGRAWINFO, &hiddevinfo);
190 
191                     if (status != IOCTL_SUCCESS) {
192                         DBG_ERROR("ioctl cmd:HIDIOCGRAWINFO failed for %s", hidDevice);
193                     }
194                     else {
195                         if(hiddevinfo.vendor == 0x22b8 && hiddevinfo.product == 0x0938) {
196                             DBG_TRACE("Found HD Dock: %s", hidDevice);
197                             break;
198                         }
199                         else {
200                             DBG_ERROR("Device: %s not a HD dock", hidDevice);
201                             close(hidDevice);
202                         }
203                     }
204                     // TODO: You cant do this.
205                     hidDevice[11]++;
206                 }
207             }
208 
209             hidDevice[11] = '0';
210         }
211         else if (protocolType == PROTOCOL_UART) {
212             globalProtocol = PROTOCOL_UART;
213         }
214     }
215     else if (buf[0] == DOCK_NOT_ATTACHED) {
216         globalState = GLOBAL_STATE_UNDOCKED;
217     }
218 
219     close(switchFd);
220 }
221 
222 
waitForUevents()223 static void waitForUevents() {
224     fd_set accySet;
225     char msg[1024];
226     int nready, status;
227 
228     FD_ZERO(&accySet);
229     FD_SET(ueventFd, &accySet);
230 
231     /* at powerup, we might have missed the uevent. So, read switch */
232     readSwitchState(PROTOCOL_HID);
233 
234     if (globalState == GLOBAL_STATE_DOCKED) {
235         DBG_TRACE("HID Dock attached at Power up");
236         sem_post(&SigAccyProtStart);
237     }
238     else {
239         readSwitchState(PROTOCOL_UART);
240         if (globalState == GLOBAL_STATE_DOCKED) {
241             DBG_TRACE("UART Dock attached at Power up");
242             sem_post(&SigAccyProtStart);
243         }
244     }
245 
246     while(1) {
247         nready = select(ueventFd+1, &accySet, NULL, NULL, NULL);
248 
249         if (nready > 0) {
250             if (FD_ISSET(ueventFd, &accySet)) {
251                 status = recv(ueventFd, msg, sizeof(msg), MSG_DONTWAIT);
252                 if ((status > 0) && (strcasestr(msg, "whisper_hid")) && (strcasestr(msg, "switch"))) {
253                     readSwitchState(PROTOCOL_HID);
254                     DBG_TRACE("HID: SEM POST after readSwitchState %d", globalState);
255                     sem_post(&SigAccyProtStart);
256                 }
257                 else if ((status > 0) && (strcasestr(msg, "whisper")) && (strcasestr(msg, "switch"))) {
258                     readSwitchState(PROTOCOL_UART);
259                     DBG_TRACE("UART: SEM POST after readSwitchState %d", globalState);
260                     sem_post(&SigAccyProtStart);
261                 }
262             }
263         }
264         else {
265             DBG_ERROR("Select errored out. nready = %d, errno = %s", nready, strerror(errno));
266         }
267     }
268 }
269 
270 
accySpawnThread()271 static int accySpawnThread() {
272     pthread_t id;
273 
274     if (pthread_create(&id, NULL,  (void *(*)(void *))accyProtDaemon, NULL) != 0) {
275         DBG_ERROR("Pthread create failed. errno = %s", strerror(errno));
276         return 0;
277     }
278 
279     return 1;
280 }
281 
282 /** Responsible for protocol communication */
accyProtDaemon(void * arg)283 static void accyProtDaemon(void *arg) {
284     struct sched_param sched;
285     int currentPolicy, tryWakeup, tryComm;
286     pthread_t threadId;
287     uint8_t  wakeupSuccess;
288     unsigned int dockDetails;
289     uint8_t dockType = NO_DOCK;
290     int status;
291     struct timespec ts;
292     struct timeval tv;
293     uint8_t statusFuse[8], FSNo[8], RomSN[8], RomRNo[8];
294     char devInfo[32];
295     char devProp[8];
296 
297     threadId = pthread_self();
298     status = pthread_getschedparam(threadId, &currentPolicy, &sched);
299 
300     if (status != 0) {
301        DBG_ERROR("pthread_getschedparam error. erno = %s", strerror(status));
302        return;
303     }
304 
305     currentPolicy = SCHED_RR;
306     sched.sched_priority = 70;
307 
308     status = pthread_setschedparam(threadId, currentPolicy, &sched);
309     if (status != 0) {
310         DBG_ERROR("pthread_setschedparam error. erno = %s", strerror(status));
311         return;
312     }
313 
314     switchUser();
315 
316     while(1) {
317         do {
318             status = sem_wait(&SigAccyProtStart);
319         } while (status < 0 && errno == EINTR);
320 
321         if (status == -1) {
322             DBG_ERROR("SEM WAIT failed with -1. errno = %s", strerror(errno));
323             break;
324         }
325 
326         /* If already undocked, why do anything */
327         if (globalState == GLOBAL_STATE_UNDOCKED)  {
328             DBG_TRACE("Thread. GLOBAL_STATE_UNDOCKED");
329             continue;
330         }
331 
332         if (globalProtocol == PROTOCOL_UART) {
333             doIoctl(CPCAP_IOCTL_ACCY_WHISPER, CPCAP_WHISPER_ENABLE_UART, NULL, NULL);
334         }
335 
336         wakeLock = acquire_wake_lock(PARTIAL_WAKE_LOCK, wakeLockString);
337         tryComm = 1;
338         while (tryComm && (globalState == GLOBAL_STATE_DOCKED)) {
339             if (globalProtocol == PROTOCOL_UART) {
340                 if (SHA_SUCCESS == SHAP_OpenChannel()) {
341                     tryWakeup = 1;
342                     wakeupSuccess = 0;
343                     while (tryWakeup) {
344                         if (SHAC_Wakeup() == SHA_SUCCESS) {
345                             DBG_TRACE("WAKEUP SUCCESS %d ", tryWakeup);
346                             tryWakeup = 0;
347                             wakeupSuccess = 1;
348                         }
349                         else {
350                             if (tryWakeup == MAX_TRY_WAKEUP) {
351                                 DBG_ERROR("GIVING UP WAKEUP after %d tries", tryWakeup);
352                                 tryWakeup = 0;
353                             }
354                             else {
355                                 DBG_TRACE("TRYING WAKEUP ONCE MORE");
356                                 ts.tv_sec = 0;
357                                 ts.tv_nsec = 10000000; // 10 ms
358                                 nanosleep(&ts, NULL);
359                                 tryWakeup++;
360                             }
361                         }
362 
363                         if (globalState == GLOBAL_STATE_UNDOCKED) {
364                             tryWakeup = 0;
365                         }
366                     }
367 
368                     if ((wakeupSuccess)  && (globalState == GLOBAL_STATE_DOCKED)) {
369                         DBG_TRACE("Reading Status & MfgId");
370                         // Read Status fuses and MfgId fuses
371                         status = SHAC_Read(0x01, 0x0002);
372                         if (status == SHA_SUCCESS) {
373                             copyResults(8, statusFuse);
374                             // TODO: bytes in wrong order for some reason??
375                             uint8_t temp[2];
376                             temp[0] = statusFuse[1];
377                             temp[1] = statusFuse[3];
378                             statusFuse[1] = temp[1];
379                             statusFuse[3] = temp[0];
380                         }
381 
382                         if (globalState == GLOBAL_STATE_DOCKED && status == SHA_SUCCESS) {
383                             DBG_TRACE("Reading Serial Number");
384                             // Read Fuse Serial number value
385                             status = SHAC_Read(0x01, 0x0003);
386                             if (status == SHA_SUCCESS) {
387                                 copyResults(8, FSNo);
388                             }
389                         }
390 
391                         if (globalState == GLOBAL_STATE_DOCKED && status == SHA_SUCCESS) {
392                             DBG_TRACE("Reading ROM MfgId and ROM SN");
393                             // ROM MfgId and ROM SN
394                             status = SHAC_Read(0x00, 0x0000);
395                             if (status == SHA_SUCCESS) {
396                                 copyResults(8, RomSN);
397 				DBG_TRACE("Authentication succeed");
398                                 globalState = GLOBAL_STATE_DOCKED_IDSUCC;
399                             }
400                         }
401                     }
402                 }
403 
404                 SHAP_CloseChannel();
405             }
406             else if (globalProtocol == PROTOCOL_HID) {
407                 uint8_t writebuff[65] = {0x0};
408                 uint8_t readbuff[65] = {0x0};
409                 uint8_t displaybuff[65] = {0x0};
410                 int hidStatus;
411 
412                 DBG_TRACE("HID: Sending status query");
413                 hidStatus = HID_FAILURE;
414                 memset(writebuff,0x00,sizeof(writebuff));
415                 memcpy(writebuff, hidStatusQuery, sizeof(hidStatusQuery));
416 
417                 status = write(hidFd, writebuff, HID_STATUS_QUERY_LENGTH);
418                 if (status != HID_STATUS_QUERY_LENGTH) {
419                     DBG_ERROR("Failed writing status query (errno = %s)", strerror(errno));
420                 }
421                 else {
422                     hidStatus = HID_SUCCESS;
423                 }
424 
425                 if (globalState == GLOBAL_STATE_DOCKED && hidStatus == HID_SUCCESS) {
426                     DBG_TRACE("HID: Reading status query response");
427                     status = read(hidFd, readbuff, HID_STATUS_MSG_LENGTH);
428 
429                     if (status != HID_STATUS_MSG_LENGTH) {
430                         DBG_ERROR("HID: Failed reading status query response, errno = %s", strerror(errno));
431                         hidStatus = HID_FAILURE;
432                     }
433                     else {
434                         DBG_TRACE("Contents of receive buffer");
435                         DBG_TRACE("first 3 bytes: %02X%02X%02X", readbuff[0], readbuff[1], readbuff[2]);
436                         DBG_TRACE("Status: %02X%02X", readbuff[3], readbuff[4]);
437                         DBG_TRACE("Ref Num: %02X%02X", readbuff[5], readbuff[6]);
438                         DBG_TRACE("Version: %s", &readbuff[6]);
439                     }
440                 }
441 
442                 if (globalState == GLOBAL_STATE_DOCKED && hidStatus == HID_SUCCESS) {
443                     DBG_TRACE("HID: Sending ID query");
444                     memset(writebuff,0x00,sizeof(writebuff));
445                     memcpy(writebuff, hidIdQuery, sizeof(hidIdQuery));
446 
447                     status = write(hidFd, writebuff, HID_ID_QUERY_LENGTH);
448                     if (status != HID_ID_QUERY_LENGTH) {
449                         DBG_ERROR("HID: Error writing ID query, %d", status);
450                         hidStatus = HID_FAILURE;
451                     }
452                 }
453 
454                 if (globalState == GLOBAL_STATE_DOCKED && hidStatus == HID_SUCCESS) {
455                     DBG_TRACE("Reading ID query response");
456                     status = read(hidFd, readbuff, HID_ID_MSG_LENGTH);
457 
458                     if (status != HID_ID_MSG_LENGTH) {
459                         DBG_ERROR("HID: Error reading ID query response, errno = %s", strerror(errno));
460                         hidStatus = HID_FAILURE;
461                     }
462                     else {
463                         DBG_TRACE("Contents of receive buffer");
464                         DBG_TRACE("first 3-2 bytes: %02X%02X%02X", readbuff[0], readbuff[1], readbuff[2]);
465                         DBG_TRACE("Status: %02X%02X", readbuff[3], readbuff[4]);
466                         DBG_TRACE("Ref Num: %02X%02X", readbuff[5], readbuff[6]);
467                         DBG_TRACE("SEMU ID: %02X%02X%02X", readbuff[7], readbuff[8], readbuff[9]);
468                         DBG_TRACE("Manufacturer ID: %02X", readbuff[10]);
469                         DBG_TRACE("ROM Revision: %02X%02X%02X%02X", readbuff[11], readbuff[12], readbuff[13], readbuff[14]);
470                         DBG_TRACE("Fuse SN: %02X%02X%02X%02X", readbuff[15], readbuff[16], readbuff[17], readbuff[18]);
471                         DBG_TRACE("ROM SN: %02X%02X", readbuff[19], readbuff[20]);
472 
473                         statusFuse[1] = readbuff[6];
474                         statusFuse[2] = readbuff[7];
475                         statusFuse[3] = readbuff[8];
476                         FSNo[1] = readbuff[14];
477                         FSNo[2] = readbuff[15];
478                         FSNo[3] = readbuff[16];
479                         FSNo[4] = readbuff[17];
480                         RomSN[3] = readbuff[18];
481                         RomSN[4] = readbuff[19];
482 
483                         globalState = GLOBAL_STATE_DOCKED_IDSUCC;
484                     }
485                 }
486             }
487 
488             if (globalState == GLOBAL_STATE_DOCKED_IDSUCC) {
489                 dockType = NO_DOCK;
490                 if (statusFuse[1] == 0x0A && statusFuse[2] == 0xC0) {
491                     dockType = LE_DOCK;
492                     DBG_TRACE("It's a Low End Dock");
493                 }
494                 else if (statusFuse[1] == 0x12 && statusFuse[2] == 0xC0 && statusFuse[3] == 0x00) {
495                     dockType = CAR_DOCK;
496                     DBG_TRACE("It's a Car Dock");
497                 }
498                 else if (statusFuse[1] == 0x1A && statusFuse[2] == 0x80 && statusFuse[3] == 0x00) {
499                     dockType = HE_DOCK;
500                     DBG_TRACE("It's a High End Dock");
501                 }
502 
503                 /* Format the output */
504                 createOutput(&FSNo[1],&devInfo[0], 4);
505                 createOutput(&RomSN[3],&devInfo[8], 2);
506                 devInfo[12] = 0;
507 
508                 createOutput(&statusFuse[1], &devProp[0], 3);
509                 devProp[6] = 0;
510 
511                 DBG_TRACE("ID SUCCESS %s", devInfo);
512                 if(dockType == NO_DOCK)
513                     DBG_TRACE("UNKNOWN STATUS FUSES <%d><%d><%d>\n", statusFuse[1], statusFuse[2], statusFuse[3]);
514 
515                 tryComm = 0;
516                 dockDetails = ID_SUCCESS;
517                 dockDetails |= (dockType << DOCK_TYPE_OFFSET);
518                 doIoctl(CPCAP_IOCTL_ACCY_WHISPER, dockDetails, devInfo, devProp);
519                 globalState = GLOBAL_STATE_DOCKED_IDSUCC;
520                 memset(devInfo,0x00,sizeof(devInfo));
521                 memset(devProp,0x00,sizeof(devProp));
522             }
523 
524             /* if the global state is still docked, then increment the retry counter */
525             if (globalState == GLOBAL_STATE_DOCKED) {
526                 if (tryComm == MAX_TRY_COMM) {
527                     DBG_ERROR("GIVING UP AFTER %d tries", tryComm);
528                     tryComm = 0;
529 
530                     dockDetails = 0; // set bit 0, for AUTH to be failure
531                     doIoctl(CPCAP_IOCTL_ACCY_WHISPER, dockDetails, NULL, NULL);
532 
533                     globalState = GLOBAL_STATE_DOCKED_IDFAIL;
534                 }
535                 else {
536                     ts.tv_sec = 0;
537                     ts.tv_nsec = 100000000; // 100 ms
538                     nanosleep(&ts, NULL);
539 
540                     tryComm++;
541                     DBG_TRACE("Trying COMM %d time", tryComm);
542                 }
543             }
544         }
545 
546         if (wakeLock) {
547             release_wake_lock(wakeLockString);
548             wakeLock = 0;
549         }
550     }
551 }
552 
553 
createOutput(uint8_t * inp,char * out,int bytes)554 static void createOutput(uint8_t *inp, char *out, int bytes) {
555     int i, j;
556 
557     for (i = 0; i < bytes; i++) {
558         j = (inp[i]  & 0x0F);
559         out[i*2+1] = xintToChar[j];
560         j = ((inp[i] >> 4) & 0xFF);
561         out[i*2] = xintToChar[j];
562     }
563 }
564 
565 
accySigHandler(signed int signal)566 static void accySigHandler(signed int signal) {
567     switch(signal) {
568         case SIGINT:
569         case SIGKILL:
570         case SIGTERM:
571              /* cose fds */
572             if (cpcapFd > 0)
573                 close(cpcapFd);
574             if (ttyFd > 0)
575                 close(ttyFd);
576             if (hidFd > 0)
577                 close(hidFd);
578             exit(0);
579             break;
580         default:
581             break;
582     }
583 }
584 
585 
accyInit(void)586 static int accyInit(void) {
587     struct sockaddr_nl addr;
588     int sz = 64*1024;
589     int s;
590     struct sigaction shutdownAction;
591     struct stat statBuf;
592 
593 #if defined(LOG_ACCY_FS)
594     if(stat(LOG_FILE_PATH, &statBuf) == 0) {
595         logFp = fopen(LOG_FILE_NAME, "w");
596         if (logFp == NULL) {
597             ALOGE("whisperd: Unable to open the Logfile %s", LOG_FILE_NAME);
598         }
599     }
600 #endif
601 
602     cpcapFd = open("/dev/cpcap", O_RDWR);
603 
604     if (cpcapFd == -1) {
605         DBG_ERROR("/dev/cpcap could not be opened. err = %s", strerror(errno));
606     }
607     else {
608         DBG_TRACE("/dev/cpcap opened: %d", cpcapFd);
609     }
610 
611     /* Setup the shutdown action. */
612     shutdownAction.sa_handler = accySigHandler;
613     sigemptyset(&shutdownAction.sa_mask);
614     shutdownAction.sa_flags = 0;
615 
616     /* Setup the signal handler. */
617     sigaction(SIGINT, &shutdownAction, NULL);
618     sigaction(SIGKILL, &shutdownAction, NULL);
619     sigaction(SIGTERM, &shutdownAction, NULL);
620 
621     globalState = GLOBAL_STATE_UNDOCKED;
622 
623     memset(&addr, 0, sizeof(addr));
624     addr.nl_family = AF_NETLINK;
625     addr.nl_pid = getpid();
626     addr.nl_groups = 0xffffffff;
627 
628     s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
629     if (s < 0) {
630         DBG_ERROR("Socket failed. err = %s", strerror(errno));
631         return 0;
632     }
633 
634     setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
635 
636     if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
637         DBG_ERROR("Bind failed. errno = %d", errno);
638         close(s);
639         return 0;
640     }
641 
642     ueventFd = s;
643 
644     return (ueventFd > 0);
645 }
646 
647 
648 
doIoctl(int cmd,unsigned int data,char * dev_id,char * dev_prop)649 void doIoctl(int cmd, unsigned int data, char *dev_id, char *dev_prop) {
650     int i, status = -1;
651     struct timespec ts;
652     struct cpcap_whisper_request req;
653 
654     memset(req.dock_id, 0, CPCAP_WHISPER_ID_SIZE);
655     req.cmd = data;
656     if(dev_id != NULL)
657       strcpy(req.dock_id, dev_id);
658     if(dev_prop != NULL)
659       strcpy(req.dock_prop, dev_prop);
660 
661     for (i = 0; i < MAX_TRY_IOCTL; i++) {
662         DBG_TRACE("ioctl cmd %d: %d,", cmd, data);
663         if(dev_id == NULL) {
664             DBG_TRACE("ioctl id = NULL");
665         }
666         else {
667             DBG_TRACE("ioctl id = <%s>\n", req.dock_id);
668         }
669 
670         status = ioctl(cpcapFd, cmd, &req);
671 
672         if (status != IOCTL_SUCCESS) {
673             DBG_ERROR("ioctl returned %d with error: %d", status, errno);
674             ts.tv_sec = 0;
675             ts.tv_nsec = 50000000; // 50 ms
676             DBG_TRACE("Wait 50ms.");
677             nanosleep(&ts, NULL);
678             globalState = GLOBAL_STATE_UNDOCKED;
679         }
680         else {
681             DBG_TRACE("ioctl success");
682             globalState = GLOBAL_STATE_DOCKED;
683             break;
684         }
685     }
686 
687     if (hidFd > 0) {
688         close(hidFd);
689         hidFd = -1;
690     }
691 
692     return;
693 }
694 
695 
copyResults(int8_t cmdSize,uint8_t * out)696 static void copyResults(int8_t cmdSize, uint8_t *out) {
697     int i;
698     char charOut[128];
699 
700     mainparms = SHAC_GetData();
701 
702     createOutput(mainparms->txBuffer, charOut, cmdSize);
703     charOut[cmdSize*2] = '\0';
704 
705     DBG_TRACE("Send Value: %s", charOut);
706 
707     for(i = 0; i < mainparms->rxSize; i++) {
708             out[i] = mainparms->rxBuffer[i];
709     }
710 
711     createOutput(mainparms->rxBuffer, charOut, cmdSize);
712     charOut[cmdSize*2] = '\0';
713     DBG_TRACE("Receive Value: = %s", charOut);
714 }
715 
716 
717 
main(int argc,char * argv[])718 int main(int argc, char *argv[]) {
719     int retVal;
720 
721     retVal = accyInit();
722 
723     if (retVal <= 0) {
724        DBG_ERROR("accyInit failed");
725     }
726 
727     if (sem_init(&SigAccyProtStart, 0, 0) != 0) {
728         DBG_ERROR("Sem_init failed. errno = %d", errno);
729     }
730 
731     //TODO:  First time failure to set parameters
732     SHAP_OpenChannel();
733     SHAP_CloseFile();
734 
735     retVal = accySpawnThread();
736 
737     switchUser();
738     waitForUevents();
739 
740     return 1;
741 }
742 
743 
switchUser(void)744 int switchUser( void ) {
745     int status;
746 
747     status = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
748     if (status < 0) {
749         return status;
750     }
751 
752     status = setuid(AID_RADIO);
753     if (status < 0) {
754          return status;
755     }
756 
757     struct __user_cap_header_struct header;
758     struct __user_cap_data_struct cap;
759     header.version = _LINUX_CAPABILITY_VERSION;
760     header.pid = 0;
761     cap.effective = cap.permitted = 1 << CAP_NET_ADMIN;
762     cap.inheritable = 0;
763     status = capset(&header, &cap);
764 
765     return status;
766 }
767 
768