/****************************************************** # File: linux_lib.c # Associated file: linux.lib # Description: Both linux.lib and linux_lib.c provide an # OS independent interface to the underlying Linux OS. # They themselves contain all the OS dependent details. # linux_lib.c provides standard IPC interfaces to the upper # level. Four standard functions are defined. # (1) sys_init : to initialize the IPC handling system, must be called # (2) ipc_init : to initialize the IPC channel # (3) ipc_write : to write to the channel # (4) ipc_read : to read from the channel *****************************************************************/ #include #include #include #include #include #include #include "linux_lib.h" #include #include #include #include #ifdef DEBUG #define TRACE(fmt, msg...) { \ if (1) { \ fprintf(stderr, "["); \ fprintf(stderr, __FUNCTION__); \ fprintf(stderr, "] "fmt"\n", ##msg); \ } \ } #else #define TRACE(fmt, msg...) #endif /* Supporting data structure */ /* PIPE */ #define MAX_NUM_PIPE 32 #define PIPE_ID_START 4096 #define PIPE_ID_END(x) (PIPE_ID_START + (x)) static int pipe_index; static int pipe_write_id[MAX_NUM_PIPE]; static int pipe_read_id[MAX_NUM_PIPE]; /* MSG QUEUE */ #define MAX_MSG_SIZE #define MAX_NUM_MSG 32 #define MSG_ID_START 8192 #define MSG_ID_END(x) (MSG_ID_START + (x)) #define MSG_TYPE_HEAD 21 #define MSG_TYPE_DATA 77 #define MSG_TYPE_ALLDATA 99 static int msg_index; static int msg_id[MAX_NUM_MSG]; struct mymsgbuf { long mtype; /* message type, must be > 0 */ long mtext; /* message data */ }; void sys_init() { pipe_index = 0; msg_index = 0; #ifdef IPAQ_ONLY setup_serial_com(); send_pulse(20); #endif return; } void sys_end() { #ifdef SIM_ONLY __asm__ __volatile__ ( "mov r6, #0\n" "mov pc, r6\n" ); #endif #ifdef IPAQ_ONLY send_pulse(20); #endif } static void sys_fault(const char *msg) { #ifdef SIM_ONLY perror(msg); usleep(20000); __asm__ __volatile__ ( "mov r6, #0\n" "mov pc, r6\n" ); #endif perror(msg); } int ipc_init(int ipc_type, int blocking) { int id, ret_id; int ret_status; int pipe_id[2]; int msg_key = 0x1234; switch (ipc_type) { case LINUX_MSGQUE: /* Don't use IPC_PRIVATE */ id = msgget(msg_key++, IPC_CREAT | 0666); if (id >= 0) { msg_id[msg_index] = id; ret_id = msg_index + MSG_ID_START; msg_index++; } else { sys_fault("Message queue init failed !"); ret_id = -1; } break; case LINUX_PIPE: ret_status = pipe(pipe_id); if (ret_status >= 0) { pipe_read_id[pipe_index] = pipe_id[0]; pipe_write_id[pipe_index] = pipe_id[1]; ret_id = pipe_index + PIPE_ID_START; pipe_index++; } else { sys_fault("Pipe init failed !"); ret_id = -1; } break; default: ret_id = -1; break; } TRACE("ipc_type = %d, ret_id = %d\n", ipc_type, ret_id); return(ret_id); } void ipc_write(int ipc_type, int ipc_id, char *data, int length) { int index, id; struct mymsgbuf msghead; struct mymsgbuf *msgdata; char *data_ptr; int i; int ret_val; char temp[1024]; switch (ipc_type) { case LINUX_MSGQUE: if ((ipc_id >= MSG_ID_START) && (ipc_id < MSG_ID_END(msg_index))) { index = ipc_id - MSG_ID_START; id = msg_id[index]; if (length > sizeof(long)) { msghead.mtype = MSG_TYPE_HEAD; msghead.mtext = *((long *)data); ret_val = msgsnd(id, (struct msgbuf *) &msghead, sizeof(long), 0); if (ret_val == -1) { sprintf(temp, "MSG(1): write %d bytes failed !", sizeof(long)); sys_fault(temp); } msgdata = (struct mymsgbuf *) (data + sizeof(long)) ; msgdata->mtype = MSG_TYPE_DATA; ret_val = msgsnd(id, msgdata, length - sizeof(long), 0); if (ret_val == -1) { sprintf(temp, "MSG(2): write %d bytes failed !", length - sizeof(long)); sys_fault(temp); } } else { msghead.mtype = MSG_TYPE_ALLDATA; data_ptr = (char *) &(msghead.mtext); for (i=0;i= PIPE_ID_START) && (ipc_id < PIPE_ID_END(pipe_index))) { index = ipc_id - PIPE_ID_START; id = pipe_write_id[index]; write(id, data, length); } else { sys_fault("Invalid pipe id !"); } break; default: break; } return; } void ipc_read(int ipc_type, int ipc_id, char *buf, int length) { int index, id; struct mymsgbuf msghead; struct msgbuf *msgdata; long *head; char *data_ptr; int i; int numbyte; char temp[1024]; static int count=0; TRACE("%d: ipc_type = %d, ipc_id = %d, length = %d\n", count++, ipc_type, ipc_id, length); switch (ipc_type) { case LINUX_MSGQUE: if ((ipc_id >= MSG_ID_START) && (ipc_id < MSG_ID_END(msg_index))) { index = ipc_id - MSG_ID_START; id = msg_id[index]; if (length > sizeof(long)) { numbyte = msgrcv(id, (struct msgbuf *) &msghead, sizeof(long), MSG_TYPE_HEAD, MSG_NOERROR); TRACE("MSG(1) : read %d bytes\n", numbyte); if (numbyte != sizeof(long)) { sprintf(temp, "MSG(1): read %d bytes failed, actual = %d", sizeof(long), numbyte); sys_fault(temp); } numbyte = msgrcv(id, (struct msgbuf *) (buf + sizeof(long)), (length - sizeof(long)), MSG_TYPE_DATA, MSG_NOERROR); TRACE("MSG(2) : read %d bytes\n", numbyte); if (numbyte != (length - sizeof(long))) { sprintf(temp, "MSG(2): read %d bytes failed, actual = %d", length - sizeof(long), numbyte); sys_fault(temp); } head = (long *) buf; *head = msghead.mtext; } else { numbyte = msgrcv(id, (struct msgbuf *) &msghead, sizeof(long), MSG_TYPE_ALLDATA, MSG_NOERROR); TRACE("MSG(3) : read %d bytes\n", numbyte); if (numbyte != sizeof(long)) { sprintf(temp, "MSG(3): read %d bytes failed, actual = %d", sizeof(long), numbyte); sys_fault(temp); } data_ptr = (char *) &(msghead.mtext); for (i=0;i= PIPE_ID_START) && (ipc_id < PIPE_ID_END(pipe_index))) { index = ipc_id - PIPE_ID_START; id = pipe_read_id[index]; read(id, buf, length); } else { sys_fault("Invalid pipe id !"); } break; default: break; } } /* ---------------- IPAQ Specifics ------------------ */ static int fd; static buf[4096]; void setup_serial_com() { struct termios options; memset(buf, 4096, 0x00); /* Open serial device */ fd = open("/dev/ttySA0", O_WRONLY | O_NOCTTY | O_NDELAY); fcntl(fd, F_SETFL, 0); printf("Opened ttySA0 : %x\n", fd); // get current options tcgetattr(fd, &options); // set raw input, 1 second timeout options.c_cflag |= (CLOCAL | CREAD); options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_oflag &= ~OPOST; options.c_cc[VMIN] = 0; options.c_cc[VTIME] = 10; return; } void send_pulse(int num) { int nbytes; nbytes = write(fd, buf, num); return; }