reverted varianttype
[profile/ivi/automotive-message-broker.git] / plugins / common / cansocket.cpp
1 /*
2 Copyright (C) 2012 Intel Corporation
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include <string.h>
20 #include <sys/ioctl.h>
21 #include <unistd.h>
22 #include <sys/socket.h>
23
24 #include "logger.h"
25 #include "cansocket.h"
26
27
28 CANSocket::CANSocket() :
29     mSocket(-1)
30 {
31     LOG_TRACE("");
32 }
33
34 CANSocket::~CANSocket()
35 {
36     LOG_TRACE("");
37
38     stop();
39 }
40
41 bool CANSocket::start(const char* ifName)
42 {
43     LOG_TRACE("");
44
45     if(mSocket < 0) {
46         if(!createSocket()) {
47             LOG_ERROR("Socket error");
48         } else {
49             can_err_mask_t errorMask = 0xFFFFFFFF;
50             if(!enableCANErrors(errorMask)) {
51                 LOG_ERROR("Socket error");
52             } else {
53                 mPoll.fd = mSocket;
54                 mPoll.events = POLLIN | POLLPRI;
55                 struct ifreq ifr;
56                 memset(&ifr, 0, sizeof(ifr));
57                 strcpy(ifr.ifr_name, ifName);
58                 if(!locateInterfaceIndex(ifr)) {
59                     LOG_ERROR("Socket error");
60                     stop();
61                 } else {
62                     struct sockaddr_can addr;
63                     memset(&addr, 0, sizeof(addr));
64                     addr.can_family = AF_CAN;
65                     addr.can_ifindex = ifr.ifr_ifindex;
66                     if(!bindSocket(addr)) {
67                         LOG_ERROR("Socket error");
68                         stop();
69                     } else {
70                         return true;
71                     }
72                 }
73             }
74         }
75     }
76     return false;
77 }
78
79 void CANSocket::stop()
80 {
81     LOG_TRACE("");
82
83     if(mSocket >= 0) {
84         closeSocket();
85         mSocket = -1;
86     }
87 }
88
89 bool CANSocket::write(const struct can_frame &frame, int &bytesWritten)
90 {
91     LOG_TRACE("");
92
93     bytesWritten = (int)writeFrame(frame);
94     return bytesWritten == sizeof(struct can_frame);
95 }
96
97 CANSocket::CANSocketReadSuccess CANSocket::read(
98         struct can_frame& frame, int &bytesRead, unsigned int timeout)
99 {
100     LOG_TRACE("timeout: " << timeout);
101
102     CANSocket::CANSocketReadSuccess success;
103
104     switch(waitData(timeout)) {
105     case -1:
106         LOG_ERROR("reading error");
107         success = CANSocket::READING_FAILED;
108         break;
109     case 0:
110         bytesRead = 0;
111         success = CANSocket::READING_TIMED_OUT;
112         break;
113     default:
114         bytesRead = (int)readFrame(frame);
115         success = bytesRead >= 0 ?CANSocket::READING_SUCCEEDED : CANSocket::READING_FAILED;
116     }
117     return success;
118 }
119
120 bool CANSocket::createSocket()
121 {
122     return ((mSocket = ::socket(PF_CAN, SOCK_RAW, CAN_RAW)) >= 0);
123 }
124
125 bool CANSocket::enableCANErrors(can_err_mask_t errorMask)
126 {
127     return (setsockopt(mSocket, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &errorMask, sizeof(errorMask)) == 0);
128 }
129
130 bool CANSocket::locateInterfaceIndex(struct ifreq& ifr)
131 {
132     return (::ioctl(mSocket, SIOCGIFINDEX, &ifr) == 0);
133 }
134
135 bool CANSocket::bindSocket(struct sockaddr_can& addr)
136 {
137     return (::bind(mSocket, (struct sockaddr*)&addr, sizeof(addr)) == 0);
138 }
139
140 bool CANSocket::closeSocket()
141 {
142     return (::close(mSocket) == 0);
143 }
144
145 int CANSocket::waitData(unsigned int timeout)
146 {
147     return ::poll(&mPoll, 1, timeout);
148 }
149
150 ssize_t CANSocket::writeFrame(const can_frame& frame)
151 {
152     return ::write(mSocket, &frame, sizeof(struct can_frame));
153 }
154
155 ssize_t CANSocket::readFrame(can_frame& frame)
156 {
157     return ::recv(mSocket, &frame, sizeof(struct can_frame), 0);
158 }