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, ¤tPolicy, &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