/** @file can.c @date 2012-02-24 @author 장길석 jks@falinux.com @brief can을 사용한 통신을 담당한다. @modify 2010-08-18 (장길석) mingw와 함께 사용할 수 있는 코드 추가 @todo @bug @remark @warning */ // // 저작권 에프에이리눅스(주) // 외부공개 금지 // //---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include /// udp 개별 구조체 typedef struct { int im_server; struct sockaddr_can addr; } can_priv_t; static poll_obj_t *tmp_can_poll = NULL; // poll 관리객체없이 전송함수를 위해 #define PF_CAN 29 /* Controller Area Network. */ #define AF_CAN PF_CAN //------------------------------------------------------------------------------ /** @brief udp 소켓을 서버형태로 open 한다. @param port 포트번호 @return poll_obj_t 형태의 포인터 *///---------------------------------------------------------------------------- poll_obj_t *can_open( char *can_port, can_filter_t *rfilter, int filter_size) { struct sockaddr_can addr; poll_obj_t *obj; can_priv_t *can; int sockfd; struct ifreq ifr; int ifindex; sockfd = socket( PF_CAN, SOCK_RAW, CAN_RAW); if ( sockfd < 0 ){ perror( "can open error:" ); return NULL; } setsockopt( sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, rfilter, filter_size); // 소켓을 시스템에 연결한다. bzero( &addr, sizeof(struct sockaddr_can) ); strcpy( ifr.ifr_name, can_port); // 사용할 CAN 번호 ioctl(sockfd, SIOCGIFINDEX, &ifr); ifindex = ifr.ifr_ifindex; addr.can_family = AF_CAN; addr.can_ifindex = ifindex; if( bind( sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) { perror("udp bind error :"); close( sockfd ); return NULL; } // udp 만의 정보를 설정한다. can = (can_priv_t *)malloc( sizeof(can_priv_t) ); can->im_server = 1; memcpy( &can->addr, &addr, sizeof( can->addr)); obj = poll_add( sockfd ); obj->type = STYP_CAN; obj->priv = (void *)can; tmp_can_poll = obj; return obj; } //------------------------------------------------------------------------------ /** @brief udp 소켓을 close 한다. @param obj 폴객체 포인터 *///---------------------------------------------------------------------------- void can_close( poll_obj_t *obj ) { close( obj->fd ); if ( obj->priv ) { free( obj->priv ); } poll_delete( obj ); if ( tmp_can_poll == obj ) tmp_can_poll = NULL; } //------------------------------------------------------------------------------ /** @brief udp 소켓을 통해 데이타를 전송한다. @param obj 폴객체 포인터 @param host 상대방 IP 나 호스트이름 문자열포인터 @param port 상대방 포트번호 @param buf 전송버퍼 @param len 버퍼의 길이 @return 전송한 데이타 개수 *///---------------------------------------------------------------------------- int can_write( poll_obj_t *obj, can_frame_t *frame) { struct sockaddr_can *p_addr; can_priv_t *p_can; int wrcnt; p_can = ( can_priv_t *)obj->priv; p_addr = &p_can->addr; wrcnt = sendto( obj->fd, frame, sizeof( can_frame_t), 0, (struct sockaddr*)p_addr, sizeof( struct sockaddr_can)); if ( 0 > wrcnt ){ perror( "can send error:" ); } return wrcnt; } //------------------------------------------------------------------------------ /** @brief udp 소켓을 통해 데이타를 읽는다. @param obj 폴객체 포인터 @param len 버퍼의 길이 @return 전송된 데이타 개수 *///---------------------------------------------------------------------------- int can_read( poll_obj_t *obj, can_frame_t *frame) { int rdcnt; rdcnt = read( obj->fd, frame, sizeof(can_frame_t)); if ( 0 > rdcnt ) { perror( "can recv error:" ); } return rdcnt; } //------------------------------------------------------------------------------ /** @brief poll 객체없이 udp 소켓을 통해 데이타를 전송한다. @param host 상대방 IP 나 호스트이름 문자열포인터 @param port 상대방 포트번호 @param buf 전송버퍼 @param len 버퍼의 길이 @return 전송한 데이타 개수 @remark can_open_server(), can_open_client() 함수는 한번 호출되어야 한다. *///---------------------------------------------------------------------------- int can_write_simple( can_frame_t *frame ) { if ( tmp_can_poll ) { return can_write( tmp_can_poll, frame); } return -1; } //------------------------------------------------------------------------------ /** @brief poll 객체없이 udp 소켓을 통해 데이타를 읽는다. @param buf 전송버퍼 @param len 버퍼의 길이 @return 전송된 데이타 개수 @remark can_open_server(), can_open_client() 함수는 한번 호출되어야 한다. *///---------------------------------------------------------------------------- int can_read_simple( can_frame_t *frame ) { if ( tmp_can_poll ) { return can_read( tmp_can_poll, frame); } return -1; }