net: Add SocketCAN support

This commit is contained in:
Peter van der Perk 2020-06-15 10:23:25 +02:00 committed by patacongo
parent a607e6257f
commit 55d9e5f7af
54 changed files with 5741 additions and 114 deletions

View file

@ -86,7 +86,8 @@
*
****************************************************************************/
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
ssize_t file_write(FAR struct file *filep, FAR const void *buf,
size_t nbytes)
{
FAR struct inode *inode;
@ -149,8 +150,10 @@ ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes)
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
{
#ifdef CONFIG_NET_TCP
/* Write to a socket descriptor is equivalent to send with flags == 0. */
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_CAN)
/* Write to a socket descriptor is equivalent to
* send with flags == 0.
*/
ret = nx_send(fd, buf, nbytes, 0);
#else

View file

@ -136,6 +136,18 @@ struct mii_ioctl_data_s
uint16_t val_out; /* PHY output data */
};
/* Structure passed to get or set the CAN bitrate
* SIOCxCANBITRATE ioctl commands.
*/
struct can_ioctl_data_s
{
uint16_t arbi_bitrate; /* Classic CAN / Arbitration phase bitrate kbit/s */
uint16_t arbi_samplep; /* Classic CAN / Arbitration phase input % */
uint16_t data_bitrate; /* Data phase bitrate kbit/s */
uint16_t data_samplep; /* Data phase sample point % */
};
/* There are two forms of the I/F request structure. One for IPv6 and one for IPv4.
* Notice that they are (and must be) cast compatible and really different only
* in the size of the structure allocation.
@ -158,6 +170,7 @@ struct lifreq
uint8_t lifru_flags; /* Interface flags */
struct mii_ioctl_notify_s llfru_mii_notify; /* PHY event notification */
struct mii_ioctl_data_s lifru_mii_data; /* MII request data */
struct can_ioctl_data_s lifru_can_data; /* CAN bitrate request data */
} lifr_ifru;
};
@ -196,6 +209,9 @@ struct lifconf
struct ifreq
{
char ifr_name[IFNAMSIZ]; /* Network device name (e.g. "eth0") */
#ifdef CONFIG_NETDEV_IFINDEX
int16_t ifr_ifindex; /* Interface index */
#endif
union
{
struct sockaddr ifru_addr; /* IP Address */
@ -208,6 +224,7 @@ struct ifreq
uint8_t ifru_flags; /* Interface flags */
struct mii_ioctl_notify_s ifru_mii_notify; /* PHY event notification */
struct mii_ioctl_data_s ifru_mii_data; /* MII request data */
struct can_ioctl_data_s ifru_can_data; /* CAN bitrate request data */
} ifr_ifru;
};
@ -226,7 +243,7 @@ struct ifreq
#define ifr_mii_val_in ifr_ifru.ifru_mii_data.val_in /* PHY input data */
#define ifr_mii_val_out ifr_ifru.ifru_mii_data.val_out /* PHY output data */
/* Used only with the SIOCGIFCONF IOCTL command*/
/* Used only with the SIOCGIFCONF IOCTL command */
struct ifconf
{

140
include/netpacket/can.h Normal file
View file

@ -0,0 +1,140 @@
/****************************************************************************
* include/netpacket/can.h
* Definitions for use with AF_PACKET sockets
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NETPACKET_CAN_H
#define __INCLUDE_NETPACKET_CAN_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000 /* EFF/SFF is set in the MSB */
#define CAN_RTR_FLAG 0x40000000 /* Remote transmission request */
#define CAN_ERR_FLAG 0x20000000 /* Error message frame */
/* Valid bits in CAN ID for frame formats */
#define CAN_SFF_MASK 0x000007ff /* Standard frame format (SFF) */
#define CAN_EFF_MASK 0x1fffffff /* Extended frame format (EFF) */
#define CAN_ERR_MASK 0x1fffffff /* Omit EFF, RTR, ERR flags */
#define CAN_MTU (sizeof(struct can_frame))
#define CANFD_MTU (sizeof(struct canfd_frame))
/* PF_CAN protocols */
#define CAN_RAW 1 /* RAW sockets */
#define CAN_BCM 2 /* Broadcast Manager */
#define CAN_TP16 3 /* VAG Transport Protocol v1.6 */
#define CAN_TP20 4 /* VAG Transport Protocol v2.0 */
#define CAN_MCNET 5 /* Bosch MCNet */
#define CAN_ISOTP 6 /* ISO 15765-2 Transport Protocol */
#define CAN_J1939 7 /* SAE J1939 */
#define CAN_NPROTO 8
/* CAN_RAW socket options */
#define CAN_RAW_FILTER (__SO_PROTOCOL + 0)
/* set 0 .. n can_filter(s) */
#define CAN_RAW_ERR_FILTER (__SO_PROTOCOL + 1)
/* set filter for error frames */
#define CAN_RAW_LOOPBACK (__SO_PROTOCOL + 2)
/* local loopback (default:on) */
#define CAN_RAW_RECV_OWN_MSGS (__SO_PROTOCOL + 3)
/* receive my own msgs (default:off) */
#define CAN_RAW_FD_FRAMES (__SO_PROTOCOL + 4)
/* allow CAN FD frames (default:off) */
#define CAN_RAW_JOIN_FILTERS (__SO_PROTOCOL + 5)
/* all filters must match to trigger */
#define CAN_RAW_TX_DEADLINE (__SO_PROTOCOL + 6)
/* Abort frame when deadline passed */
/****************************************************************************
* Public Types
****************************************************************************/
/* Controller Area Network Identifier structure
*
* Bit 0-28: CAN identifier (11/29 bit)
* Bit 29: Error message frame flag (0 = data frame, 1 = error message)
* Bit 30: Remote transmission request flag (1 = rtr frame)
* Bit 31: Frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
*/
typedef uint32_t canid_t;
/* The sockaddr structure for CAN sockets
*
* can_family: Address family number AF_CAN.
* can_ifindex: CAN network interface index.
* can_addr: Protocol specific address information
*/
struct sockaddr_can
{
sa_family_t can_family;
int16_t can_ifindex;
union
{
/* Transport protocol class address information */
struct
{
canid_t rx_id;
canid_t tx_id;
} tp;
/* J1939 address information */
struct
{
/* 8 byte name when using dynamic addressing */
uint64_t name;
/* pgn:
* 8 bit: PS in PDU2 case, else 0
* 8 bit: PF
* 1 bit: DP
* 1 bit: reserved
*/
uint32_t pgn;
/* 1 byte address */
uint8_t addr;
} j1939;
} can_addr;
};
#endif /* __INCLUDE_NETPACKET_CAN_H */

319
include/nuttx/can.h Normal file
View file

@ -0,0 +1,319 @@
/************************************************************************************
* include/nuttx/can/can.h
*
* Copyright (C) 2008, 2009, 2011-2012, 2015-2017, 2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __INCLUDE_NUTTX_CAN_CAN_H
#define __INCLUDE_NUTTX_CAN_CAN_H
/************************************************************************************
* Included Files
************************************************************************************/
#ifdef CONFIG_CAN_TXREADY
# include <nuttx/wqueue.h>
#endif
#include <queue.h>
#ifdef CONFIG_NET_CAN
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Ioctl Commands *******************************************************************/
/* Ioctl commands supported by the upper half CAN driver.
*
* CANIOC_RTR:
* Description: Send the remote transmission request and wait for the response.
* Argument: A reference to struct canioc_rtr_s
*
* Ioctl commands that may or may not be supported by the lower half CAN driver.
*
* CANIOC_ADD_STDFILTER:
* Description: Add an address filter for a standard 11 bit address.
* Argument: A reference to struct canioc_stdfilter_s
* Returned Value: A non-negative filter ID is returned on success.
* Otherwise -1 (ERROR) is returned with the errno
* variable set to indicate the nature of the error.
* Dependencies: None
*
* CANIOC_ADD_EXTFILTER:
* Description: Add an address filter for a extended 29 bit address.
* Argument: A reference to struct canioc_extfilter_s
* Returned Value: A non-negative filter ID is returned on success.
* Otherwise -1 (ERROR) is returned with the errno
* variable set to indicate the nature of the error.
* Dependencies: Requires CONFIG_CAN_EXTID=y
*
* CANIOC_DEL_STDFILTER:
* Description: Remove an address filter for a standard 11 bit address.
* Argument: The filter index previously returned by the
* CANIOC_ADD_STDFILTER command
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
* is returned with the errno variable set to indicate the
* nature of the error.
* Dependencies: None
*
* CANIOC_DEL_EXTFILTER:
* Description: Remove an address filter for a standard 29 bit address.
* Argument: The filter index previously returned by the
* CANIOC_ADD_EXTFILTER command
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
* is returned with the errno variable set to indicate the
* nature of the error.
* Dependencies: Requires CONFIG_CAN_EXTID=y
*
* CANIOC_GET_BITTIMING:
* Description: Return the current bit timing settings
* Argument: A pointer to a write-able instance of struct
* canioc_bittiming_s in which current bit timing values
* will be returned.
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
* is returned with the errno variable set to indicate the
* nature of the error.
* Dependencies: None
*
* CANIOC_SET_BITTIMING:
* Description: Set new current bit timing values
* Argument: A pointer to a read-able instance of struct
* canioc_bittiming_s in which the new bit timing values
* are provided.
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
* is returned with the errno variable set to indicate the
* nature of the error.
* Dependencies: None
*
* CANIOC_GET_CONNMODES:
* Description: Get the current bus connection modes
* Argument: A pointer to a write-able instance of struct
* canioc_connmodes_s in which the new bus modes will be returned.
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
* is returned with the errno variable set to indicate the
* nature of the error.
* Dependencies: None
*
* CANIOC_SET_CONNMODES:
* Description: Set new bus connection modes values
* Argument: A pointer to a read-able instance of struct
* canioc_connmodes_s in which the new bus modes are provided.
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
* is returned with the errno variable set to indicate the
* nature of the error.
* Dependencies: None
*
* CANIOC_BUSOFF_RECOVERY:
* Description: Initiates the BUS-OFF recovery sequence
* Argument: None
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
* is returned with the errno variable set to indicate the
* nature of the error.
* Dependencies: None
*/
#define CANIOC_RTR _CANIOC(1)
#define CANIOC_GET_BITTIMING _CANIOC(2)
#define CANIOC_SET_BITTIMING _CANIOC(3)
#define CANIOC_ADD_STDFILTER _CANIOC(4)
#define CANIOC_ADD_EXTFILTER _CANIOC(5)
#define CANIOC_DEL_STDFILTER _CANIOC(6)
#define CANIOC_DEL_EXTFILTER _CANIOC(7)
#define CANIOC_GET_CONNMODES _CANIOC(8)
#define CANIOC_SET_CONNMODES _CANIOC(9)
#define CANIOC_BUSOFF_RECOVERY _CANIOC(10)
#define CAN_FIRST 0x0001 /* First common command */
#define CAN_NCMDS 10 /* Ten common commands */
/* User defined ioctl commands are also supported. These will be forwarded
* by the upper-half CAN driver to the lower-half CAN driver via the co_ioctl()
* method fo the CAN lower-half interface. However, the lower-half driver
* must reserve a block of commands as follows in order prevent IOCTL
* command numbers from overlapping.
*
* This is generally done as follows. The first reservation for CAN driver A would
* look like:
*
* CAN_A_FIRST (CAN_FIRST + CAN_NCMDS) <- First command
* CAN_A_NCMDS 42 <- Number of commands
*
* IOCTL commands for CAN driver A would then be defined in a CAN A header file like:
*
* CANIOC_A_CMD1 _CANIOC(CAN_A_FIRST+0)
* CANIOC_A_CMD2 _CANIOC(CAN_A_FIRST+1)
* CANIOC_A_CMD3 _CANIOC(CAN_A_FIRST+2)
* ...
* CANIOC_A_CMD42 _CANIOC(CAN_A_FIRST+41)
*
* The next reservation would look like:
*
* CAN_B_FIRST (CAN_A_FIRST + CAN_A_NCMDS) <- Next command
* CAN_B_NCMDS 77 <- Number of commands
*/
/* CAN payload length and DLC definitions according to ISO 11898-1 */
#define CAN_MAX_DLC 8
#define CAN_MAX_DLEN 8
/* CAN FD payload length and DLC definitions according to ISO 11898-7 */
#define CANFD_MAX_DLC 15
#define CANFD_MAX_DLEN 64
/* Defined bits for canfd_frame.flags
*
* The use of struct canfd_frame implies the Extended Data Length (EDL) bit to
* be set in the CAN frame bitstream on the wire. The EDL bit switch turns
* the CAN controllers bitstream processor into the CAN FD mode which creates
* two new options within the CAN FD frame specification:
*
* Bit Rate Switch - to indicate a second bitrate is/was used for the payload
* Error State Indicator - represents the error state of the transmitting node
*
* As the CANFD_ESI bit is internally generated by the transmitting CAN
* controller only the CANFD_BRS bit is relevant for real CAN controllers when
* building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make
* sense for virtual CAN interfaces to test applications with echoed frames.
*/
#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
/************************************************************************************
* Public Types
************************************************************************************/
typedef FAR void *CAN_HANDLE;
struct can_response_s
{
sq_entry_t flink;
/* Message-specific data may follow */
}; /* FIXME remove */
typedef uint32_t canid_t;
/* Controller Area Network Error Message Frame Mask structure
*
* bit 0-28 : error class mask (see include/uapi/linux/can/error.h)
* bit 29-31 : set to zero
*/
typedef uint32_t can_err_mask_t;
/* struct can_frame - basic CAN frame structure
* can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
* can_dlc: frame payload length in byte (0 .. 8) aka data length code
* N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1
* mapping of the 'data length code' to the real payload length
* __pad: padding
* __res0: reserved / padding
* __res1: reserved / padding
* data: CAN frame payload (up to 8 byte)
*/
struct can_frame
{
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
uint8_t can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
uint8_t __pad; /* padding */
uint8_t __res0; /* reserved / padding */
uint8_t __res1; /* reserved / padding */
uint8_t data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};
/* struct canfd_frame - CAN flexible data rate frame structure
* can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
* len: frame payload length in byte (0 .. CANFD_MAX_DLEN)
* flags: additional flags for CAN FD
* __res0: reserved / padding
* __res1: reserved / padding
* data: CAN FD frame payload (up to CANFD_MAX_DLEN byte)
*/
struct canfd_frame
{
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
uint8_t len; /* frame payload length in byte */
uint8_t flags; /* additional flags for CAN FD */
uint8_t __res0; /* reserved / padding */
uint8_t __res1; /* reserved / padding */
uint8_t data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
};
/* struct can_filter - CAN ID based filter in can_register().
* can_id: relevant bits of CAN ID which are not masked out.
* can_mask: CAN mask (see description)
*
* Description:
* A filter matches, when
*
* <received_can_id> & mask == can_id & mask
*
* The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
* filter for error message frames (CAN_ERR_FLAG bit set in mask).
*/
struct can_filter
{
canid_t can_id;
canid_t can_mask;
};
/************************************************************************************
* Public Function Prototypes
************************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* CONFIG_CAN */
#endif /* __INCLUDE_NUTTX_CAN_CAN_H */

129
include/nuttx/can/error.h Normal file
View file

@ -0,0 +1,129 @@
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
/************************************************************************************
* linux/can/error.h
*
* Definitions of the CAN error messages to be filtered and passed to the
* user.
*
* Author: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Volkswagen nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* The provided data structures and external interfaces from this code
* are not restricted to be used by modules with a GPL compatible license.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
************************************************************************************/
#ifndef _UAPI_CAN_ERROR_H
#define _UAPI_CAN_ERROR_H
#define CAN_ERR_DLC 8 /* dlc for error message frames */
/* error class (mask) in can_id */
#define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */
#define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */
#define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
#define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */
#define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
#define CAN_ERR_BUSOFF 0x00000040U /* bus off */
#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
/* arbitration lost in bit ... / data[0] */
#define CAN_ERR_LOSTARB_UNSPEC 0x00 /* unspecified */
/* else bit number in bitstream */
/* error status of CAN-controller / data[1] */
#define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */
#define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
#define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
#define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */
#define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */
#define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */
#define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */
/* (at least one error counter exceeds */
/* the protocol-defined level of 127) */
#define CAN_ERR_CRTL_ACTIVE 0x40 /* recovered to error active state */
/* error in CAN protocol (type) / data[2] */
#define CAN_ERR_PROT_UNSPEC 0x00 /* unspecified */
#define CAN_ERR_PROT_BIT 0x01 /* single bit error */
#define CAN_ERR_PROT_FORM 0x02 /* frame format error */
#define CAN_ERR_PROT_STUFF 0x04 /* bit stuffing error */
#define CAN_ERR_PROT_BIT0 0x08 /* unable to send dominant bit */
#define CAN_ERR_PROT_BIT1 0x10 /* unable to send recessive bit */
#define CAN_ERR_PROT_OVERLOAD 0x20 /* bus overload */
#define CAN_ERR_PROT_ACTIVE 0x40 /* active error announcement */
#define CAN_ERR_PROT_TX 0x80 /* error occurred on transmission */
/* error in CAN protocol (location) / data[3] */
#define CAN_ERR_PROT_LOC_UNSPEC 0x00 /* unspecified */
#define CAN_ERR_PROT_LOC_SOF 0x03 /* start of frame */
#define CAN_ERR_PROT_LOC_ID28_21 0x02 /* ID bits 28 - 21 (SFF: 10 - 3) */
#define CAN_ERR_PROT_LOC_ID20_18 0x06 /* ID bits 20 - 18 (SFF: 2 - 0 )*/
#define CAN_ERR_PROT_LOC_SRTR 0x04 /* substitute RTR (SFF: RTR) */
#define CAN_ERR_PROT_LOC_IDE 0x05 /* identifier extension */
#define CAN_ERR_PROT_LOC_ID17_13 0x07 /* ID bits 17-13 */
#define CAN_ERR_PROT_LOC_ID12_05 0x0f /* ID bits 12-5 */
#define CAN_ERR_PROT_LOC_ID04_00 0x0e /* ID bits 4-0 */
#define CAN_ERR_PROT_LOC_RTR 0x0c /* RTR */
#define CAN_ERR_PROT_LOC_RES1 0x0d /* reserved bit 1 */
#define CAN_ERR_PROT_LOC_RES0 0x09 /* reserved bit 0 */
#define CAN_ERR_PROT_LOC_DLC 0x0b /* data length code */
#define CAN_ERR_PROT_LOC_DATA 0x0a /* data section */
#define CAN_ERR_PROT_LOC_CRC_SEQ 0x08 /* CRC sequence */
#define CAN_ERR_PROT_LOC_CRC_DEL 0x18 /* CRC delimiter */
#define CAN_ERR_PROT_LOC_ACK 0x19 /* ACK slot */
#define CAN_ERR_PROT_LOC_ACK_DEL 0x1b /* ACK delimiter */
#define CAN_ERR_PROT_LOC_EOF 0x1a /* end of frame */
#define CAN_ERR_PROT_LOC_INTERM 0x12 /* intermission */
/* error status of CAN-transceiver / data[4] */
/* CANH CANL */
#define CAN_ERR_TRX_UNSPEC 0x00 /* 0000 0000 */
#define CAN_ERR_TRX_CANH_NO_WIRE 0x04 /* 0000 0100 */
#define CAN_ERR_TRX_CANH_SHORT_TO_BAT 0x05 /* 0000 0101 */
#define CAN_ERR_TRX_CANH_SHORT_TO_VCC 0x06 /* 0000 0110 */
#define CAN_ERR_TRX_CANH_SHORT_TO_GND 0x07 /* 0000 0111 */
#define CAN_ERR_TRX_CANL_NO_WIRE 0x40 /* 0100 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_BAT 0x50 /* 0101 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_VCC 0x60 /* 0110 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */
/* controller specific additional information / data[5..7] */
#endif /* _UAPI_CAN_ERROR_H */

View file

@ -54,6 +54,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* I/O buffer allocation logic supports a throttle value for read-ahead
@ -219,6 +220,9 @@ enum iob_user_e
#endif
#ifdef CONFIG_WIRELESS_BLUETOOTH
IOBUSER_WIRELESS_BLUETOOTH,
#endif
#ifdef CONFIG_NET_CAN
IOBUSER_NET_CAN_READAHEAD,
#endif
IOBUSER_GLOBAL,
IOBUSER_NENTRIES /* MUST BE LAST ENTRY */
@ -248,7 +252,8 @@ void iob_initialize(void);
* Name: iob_alloc
*
* Description:
* Allocate an I/O buffer by taking the buffer at the head of the free list.
* Allocate an I/O buffer by taking the buffer at the head of the free
* list.
*
****************************************************************************/
@ -586,7 +591,8 @@ void iob_dump(FAR const char *msg, FAR struct iob_s *iob, unsigned int len,
* Name: iob_getuserstats
*
* Description:
* Return a reference to the IOB usage statistics for the IOB consumer/producer
* Return a reference to the IOB usage statistics for the IOB
* consumer/producer
*
* Input Parameters:
* userid - id representing the IOB producer/consumer

122
include/nuttx/net/can.h Normal file
View file

@ -0,0 +1,122 @@
/****************************************************************************
* include/nuttx/net/can.h
* Macros and definitions for the CAN link layer.
*
* Copyright (C) 2007, 2009-2012, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derived from uIP with has a similar BSD-styple license:
*
* Author: Adam Dunkels <adam@dunkels.com>
* Copyright (c) 2001-2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_NET_CAN_H
#define __INCLUDE_NUTTX_NET_CAN_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/can.h>
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_NET_CAN_CANFD
#define NET_CAN_PKTSIZE sizeof(struct canfd_frame)
#else
#define NET_CAN_PKTSIZE sizeof(struct can_frame)
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef CONFIG_NET_CAN_CANFD
/* Lookup tables convert can_dlc <-> payload len */
extern const uint8_t can_dlc_to_len[16];
extern const uint8_t len_to_can_dlc[65];
#endif
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: can_input
*
* Description:
* Handle incoming CAN frame input
*
* This function provides the interface between CAN device drivers and
* SocketCAN logic. All frames that are received should be provided to
* can_input() prior to other routing.
*
* Input Parameters:
* dev - The device driver structure containing the received packet
*
* Returned Value:
* OK The packet has been processed and can be deleted
* ERROR There is a matching connection, but could not dispatch the packet
* yet. Useful when a packet arrives before a recv call is in
* place.
*
* Assumptions:
* Called from the CAN device diver with the network locked.
*
****************************************************************************/
struct net_driver_s; /* Forward reference */
int can_input(FAR struct net_driver_s *dev);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDE_NUTTX_NET_CAN_H */

View file

@ -85,6 +85,9 @@
#define SIOCGIFCONF _SIOC(0x0018) /* Return an interface list (IPv4) */
#define SIOCGLIFCONF _SIOC(0x0019) /* Return an interface list (IPv6) */
#define SIOCGIFNAME _SIOC(0x002A) /* Get interface name string */
#define SIOCGIFINDEX _SIOC(0x002B) /* Get index based name string */
/* Interface flags */
#define SIOCSIFFLAGS _SIOC(0x001a) /* Sets the interface flags */
@ -122,6 +125,11 @@
#define SIOCTELNET _SIOC(0x0029) /* Create a Telnet sessions.
* See include/nuttx/net/telnet.h */
/* SocketCAN ****************************************************************/
#define SIOCGCANBITRATE _SIOC(0x002C) /* Get bitrate from a CAN controller */
#define SIOCSCANBITRATE _SIOC(0x002D) /* Set bitrate of a CAN controller */
/****************************************************************************
* Public Type Definitions
****************************************************************************/

View file

@ -156,7 +156,8 @@ enum net_lltype_e
NET_LL_IEEE80211, /* IEEE 802.11 */
NET_LL_IEEE802154, /* IEEE 802.15.4 MAC */
NET_LL_PKTRADIO, /* Non-standard packet radio */
NET_LL_MBIM /* CDC-MBIM USB host driver */
NET_LL_MBIM, /* CDC-MBIM USB host driver */
NET_LL_CAN /* CAN bus */
};
/* This defines a bitmap big enough for one bit for each socket option */
@ -215,6 +216,12 @@ struct sock_intf_s
CODE ssize_t (*si_recvfrom)(FAR struct socket *psock, FAR void *buf,
size_t len, int flags, FAR struct sockaddr *from,
FAR socklen_t *fromlen);
#ifdef CONFIG_NET_CMSG
CODE ssize_t (*si_recvmsg)(FAR struct socket *psock,
FAR struct msghdr *msg, int flags);
CODE ssize_t (*si_sendmsg)(FAR struct socket *psock,
FAR struct msghdr *msg, int flags);
#endif
CODE int (*si_close)(FAR struct socket *psock);
#ifdef CONFIG_NET_USRSOCK
CODE int (*si_ioctl)(FAR struct socket *psock, int cmd,
@ -271,6 +278,9 @@ struct socket
#ifdef CONFIG_NET_SOLINGER
socktimeo_t s_linger; /* Linger timeout value (in deciseconds) */
#endif
#ifdef CONFIG_NET_TIMESTAMP
int32_t s_timestamp; /* Socket timestamp enabled/disabled */
#endif
#endif
FAR void *s_conn; /* Connection inherits from struct socket_conn_s */
@ -370,6 +380,25 @@ void net_initialize(void);
int net_lock(void);
/****************************************************************************
* Name: net_trylock
*
* Description:
* Try to take the network lock only when it is currently not locked.
* Otherwise, it locks the semaphore. In either
* case, the call returns without blocking.
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* failured (probably -EAGAIN).
*
****************************************************************************/
int net_trylock(void);
/****************************************************************************
* Name: net_unlock
*

View file

@ -280,7 +280,8 @@ enum work_evtype_e
WORK_TCP_DISCONNECT, /* Notify loss of TCP connection */
WORK_UDP_READAHEAD, /* Notify that UDP read-ahead data is available */
WORK_UDP_WRITEBUFFER, /* Notify that UDP write buffer is empty */
WORK_NETLINK_RESPONSE /* Notify that Netlink response is available */
WORK_NETLINK_RESPONSE, /* Notify that Netlink response is available */
WORK_CAN_READAHEAD /* Notify that CAN read-ahead data is available */
};
/* This structure describes one notification and is provided as input to

View file

@ -62,6 +62,7 @@
#define PF_NETLINK 16 /* Netlink IPC socket */
#define PF_ROUTE PF_NETLINK /* 4.4BSD Compatibility*/
#define PF_PACKET 17 /* Low level packet interface */
#define PF_CAN 29 /* Controller Area Network (SocketCAN) */
#define PF_BLUETOOTH 31 /* Bluetooth sockets */
#define PF_IEEE802154 36 /* Low level IEEE 802.15.4 radio frame interface */
#define PF_PKTRADIO 64 /* Low level packet radio interface */
@ -78,6 +79,7 @@
#define AF_NETLINK PF_NETLINK
#define AF_ROUTE PF_ROUTE
#define AF_PACKET PF_PACKET
#define AF_CAN PF_CAN
#define AF_BLUETOOTH PF_BLUETOOTH
#define AF_IEEE802154 PF_IEEE802154
#define AF_PKTRADIO PF_PKTRADIO
@ -199,6 +201,16 @@
#define SO_TYPE 15 /* Reports the socket type (get only).
* return: int
*/
#define SO_TIMESTAMP 16 /* Generates a timestamp for each incoming packet
* arg: integer value
*/
/* The options are unsupported but included for compatibility
* and portability
*/
#define SO_SNDBUFFORCE 32
#define SO_RCVBUFFORCE 33
#define SO_RXQ_OVFL 40
/* Protocol-level socket operations. */
@ -210,6 +222,7 @@
#define SOL_L2CAP 6 /* See options in include/netpacket/bluetooth.h */
#define SOL_SCO 7 /* See options in include/netpacket/bluetooth.h */
#define SOL_RFCOMM 8 /* See options in include/netpacket/bluetooth.h */
#define SOL_CAN_RAW 9 /* See options in include/netpacket/can.h */
/* Protocol-level socket options may begin with this value */

View file

@ -39,7 +39,7 @@
#include <nuttx/config.h>
#ifdef CONFIG_NET
#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG)
#include <sys/types.h>
#include <sys/socket.h>
@ -53,7 +53,8 @@
* Function: recvmsg
*
* Description:
* The recvmsg() call is identical to recvfrom() with a NULL from parameter.
* The recvmsg() call is identical to recvfrom() with a NULL from
* parameter.
*
* Parameters:
* sockfd Socket descriptor of socket
@ -86,4 +87,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
}
}
#endif /* CONFIG_NET */
#endif /* CONFIG_NET && !CONFIG_NET_CMSG */

View file

@ -39,7 +39,7 @@
#include <nuttx/config.h>
#ifdef CONFIG_NET
#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG)
#include <sys/types.h>
#include <sys/socket.h>
@ -86,4 +86,4 @@ ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
}
}
#endif /* CONFIG_NET */
#endif /* CONFIG_NET && !CONFIG_NET_CMSG */

View file

@ -349,6 +349,7 @@ source "net/socket/Kconfig"
source "net/inet/Kconfig"
source "net/pkt/Kconfig"
source "net/local/Kconfig"
source "net/can/Kconfig"
source "net/netlink/Kconfig"
source "net/tcp/Kconfig"
source "net/udp/Kconfig"

View file

@ -52,6 +52,7 @@ include igmp/Make.defs
include pkt/Make.defs
include local/Make.defs
include mld/Make.defs
include can/Make.defs
include netlink/Make.defs
include tcp/Make.defs
include udp/Make.defs

View file

@ -106,9 +106,13 @@ const struct sock_intf_s g_bluetooth_sockif =
bluetooth_send, /* si_send */
bluetooth_sendto, /* si_sendto */
#ifdef CONFIG_NET_SENDFILE
NULL, /* si_sendfile */
NULL, /* si_sendfile */
#endif
bluetooth_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
NULL, /* si_sendmsg */
#endif
bluetooth_close /* si_close */
};
@ -243,10 +247,10 @@ static void bluetooth_addref(FAR struct socket *psock)
* Name: bluetooth_connect
*
* Description:
* bluetooth_connect() connects the local socket referred to by the structure
* 'psock' to the address specified by 'addr'. The addrlen argument
* specifies the size of 'addr'. The format of the address in 'addr' is
* determined by the address space of the socket 'psock'.
* bluetooth_connect() connects the local socket referred to by the
* structure 'psock' to the address specified by 'addr'. The addrlen
* argument specifies the size of 'addr'. The format of the address in
* 'addr' is determined by the address space of the socket 'psock'.
*
* Generally, connection-based protocol sockets may successfully
* bluetooth_connect() only once; connectionless protocol sockets may use
@ -330,7 +334,8 @@ static int bluetooth_connect(FAR struct socket *psock,
* Input Parameters:
* psock Reference to the listening socket structure
* addr Receives the address of the connecting client
* addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
* addrlen Input: allocated size of 'addr',
* Return: returned size of 'addr'
* newsock Location to return the accepted socket information.
*
* Returned Value:
@ -372,7 +377,7 @@ static int bluetooth_accept(FAR struct socket *psock,
****************************************************************************/
static int bluetooth_bind(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen)
FAR const struct sockaddr *addr, socklen_t addrlen)
{
FAR const struct sockaddr_bt_s *iaddr;
FAR struct radio_driver_s *radio;
@ -439,10 +444,10 @@ static int bluetooth_bind(FAR struct socket *psock,
* Name: bluetooth_getsockname
*
* Description:
* The bluetooth_getsockname() function retrieves the locally-bound name of the
* specified packet socket, stores this address in the sockaddr structure
* pointed to by the 'addr' argument, and stores the length of this
* address in the object pointed to by the 'addrlen' argument.
* The bluetooth_getsockname() function retrieves the locally-bound name of
* the specified packet socket, stores this address in the sockaddr
* structure pointed to by the 'addr' argument, and stores the length of
* this address in the object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
@ -501,8 +506,8 @@ static int bluetooth_getsockname(FAR struct socket *psock,
* Name: bluetooth_getpeername
*
* Description:
* The bluetooth_getpeername() function retrieves the remote-connected name of
* the specified local socket, stores this address in the sockaddr
* The bluetooth_getpeername() function retrieves the remote-connected name
* of the specified local socket, stores this address in the sockaddr
* structure pointed to by the 'addr' argument, and stores the length of
* this address in the object pointed to by the 'addrlen' argument.
*
@ -705,9 +710,10 @@ static ssize_t bluetooth_send(FAR struct socket *psock, FAR const void *buf,
*
****************************************************************************/
static ssize_t bluetooth_sendto(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags,
FAR const struct sockaddr *to, socklen_t tolen)
static ssize_t bluetooth_sendto(FAR struct socket *psock,
FAR const void *buf, size_t len, int flags,
FAR const struct sockaddr *to,
socklen_t tolen)
{
ssize_t ret;

97
net/can/Kconfig Normal file
View file

@ -0,0 +1,97 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
menu "SocketCAN Support"
config NET_CAN
bool "SocketCAN support"
default n
select NET_READAHEAD
depends on NET
---help---
Enable support for SocketCAN sockets that will permit.
This logic is a WIP. Currently only fragmentary support is
available, not enough to actually do anything of consequence.
if NET_CAN
config NET_CAN_HAVE_TX_DEADLINE
bool
default n
config NET_CAN_HAVE_CANFD
bool
default n
config CAN_CONNS
int "Number of CAN connections"
default 4
---help---
Maximum number of CAN connections (all tasks).
config NET_CAN_CANFD
bool "Enable CAN FD support"
default y
depends on NET_CAN_HAVE_CANFD
---help---
Enable CAN FD support in SocketCAN stack
config NET_CAN_SOCK_OPTS
bool "sockopt support"
default n
select NET_SOCKOPTS
select NET_CANPROTO_OPTIONS
---help---
Enable support for the CAN socket options
config NET_CAN_RAW_TX_DEADLINE
bool "TX deadline sockopt"
default n
depends on NET_CAN_SOCK_OPTS && NET_CAN_HAVE_TX_DEADLINE
select NET_CMSG
---help---
Note: Non-standard SocketCAN sockopt, but this options helps us in
real-time use cases.
When the CAN_RAW_TX_DEADLINE sockopt is enabled. The user can send
CAN frames using sendmsg() function and add a deadline timespec
value in the CMSG data. When the deadline has been passed and the
CAN frame is still in the HW TX mailbox then the CAN driver will
discard the CAN frame automatically.
config NET_CAN_RAW_DEFAULT_TX_DEADLINE
int "Default TX deadline when no deadline is given (us)"
default 0
depends on NET_CAN_RAW_TX_DEADLINE
---help---
Some applications may not use the NET_CAN_RAW_TX_DEADLINE flag.
By default their deadline becomes 0 which means it becomes infinite.
This would mean that packets from applications without the
NET_CAN_RAW_TX_DEADLINE flag, can block the TX mailboxes forever.
This config can set the default deadline when no deadline has been
given.
config NET_CAN_RAW_FILTER_MAX
int "CAN_RAW_FILTER max filter count"
default 32
depends on NET_CAN_SOCK_OPTS
---help---
Maximum number of CAN_RAW filters that can be set per CAN connection.
config NET_CAN_NOTIFIER
bool "Support CAN notifications"
default n
depends on SCHED_WORKQUEUE
select WQUEUE_NOTIFIER
---help---
Enable building of CAN notifier logic that will execute a worker
function on the low priority work queue when read-ahead data
is available or when a CAN connection is lost. This is is a general
purpose notifier, but was developed specifically to support poll()
logic where the poll must wait for these events.
endif # NET_CAN
endmenu # CAN Socket Support

48
net/can/Make.defs Normal file
View file

@ -0,0 +1,48 @@
############################################################################
# net/can/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
# Logic specific to SocketCAN socket support
ifeq ($(CONFIG_NET_CAN),y)
# Socket layer
SOCK_CSRCS += can_sockif.c
SOCK_CSRCS += can_send.c
SOCK_CSRCS += can_recvfrom.c
ifeq ($(CONFIG_NET_CAN_NOTIFIER),y)
SOCK_CSRCS += can_notifier.c
endif
ifeq ($(CONFIG_NET_CANPROTO_OPTIONS),y)
SOCK_CSRCS += can_setsockopt.c can_getsockopt.c
endif
NET_CSRCS += can_conn.c
NET_CSRCS += can_input.c
NET_CSRCS += can_callback.c
NET_CSRCS += can_poll.c
# Include can build support
DEPPATH += --dep-path can
VPATH += :can
endif # CONFIG_NET_CAN

385
net/can/can.h Normal file
View file

@ -0,0 +1,385 @@
/****************************************************************************
* net/can/can.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __NET_CAN_CAN_H
#define __NET_CAN_CAN_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <poll.h>
#include <netpacket/can.h>
#include <nuttx/semaphore.h>
#include <nuttx/can.h>
#include <nuttx/net/netdev.h>
#include "devif/devif.h"
#include "socket/socket.h"
#ifdef CONFIG_NET_CAN_NOTIFIER
# include <nuttx/wqueue.h>
#endif
#ifdef CONFIG_NET_CAN
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Allocate a new packet socket data callback */
#define can_callback_alloc(dev,conn) \
devif_callback_alloc(dev, &conn->list)
#define can_callback_free(dev,conn,cb) \
devif_conn_callback_free(dev, cb, &conn->list)
/****************************************************************************
* Public Type Definitions
****************************************************************************/
/* This is a container that holds the poll-related information */
struct can_poll_s
{
FAR struct socket *psock; /* Needed to handle loss of connection */
FAR struct net_driver_s *dev; /* Needed to free the callback structure */
struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
};
/* This "connection" structure describes the underlying state of the socket */
struct can_conn_s
{
/* Common prologue of all connection structures. */
dq_entry_t node; /* Supports a doubly linked list */
/* This is a list of NetLink connection callbacks. Each callback
* represents a thread that is stalled, waiting for a device-specific
* event.
*/
FAR struct devif_callback_s *list; /* NetLink callbacks */
FAR struct net_driver_s *dev; /* Reference to CAN device */
/* Read-ahead buffering.
*
* readahead - A singly linked list of type struct iob_qentry_s
* where the CAN/IP read-ahead data is retained.
*/
struct iob_queue_s readahead; /* remove Read-ahead buffering */
/* CAN-specific content follows */
uint8_t protocol; /* Selected CAN protocol */
int16_t crefs; /* Reference count */
/* The following is a list of poll structures of threads waiting for
* socket events.
*/
struct can_poll_s pollinfo[4]; /* FIXME make dynamic */
#ifdef CONFIG_NET_CANPROTO_OPTIONS
int32_t loopback;
int32_t recv_own_msgs;
#ifdef CONFIG_NET_CAN_CANFD
int32_t fd_frames;
#endif
struct can_filter filters[CONFIG_NET_CAN_RAW_FILTER_MAX];
int32_t filter_count;
# ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
int32_t tx_deadline;
# endif
#endif
#ifdef CONFIG_NET_TIMESTAMP
FAR struct socket *psock; /* Needed to get SO_TIMESTAMP value */
#endif
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
# define EXTERN extern "C"
extern "C"
{
#else
# define EXTERN extern
#endif
EXTERN const struct sock_intf_s g_can_sockif;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
struct sockaddr_can; /* Forward reference */
/****************************************************************************
* Name: can_initialize()
*
* Description:
* Initialize the NetLink connection structures. Called once and only
* from the networking layer.
*
****************************************************************************/
void can_initialize(void);
/****************************************************************************
* Name: can_alloc()
*
* Description:
* Allocate a new, uninitialized NetLink connection structure. This is
* normally something done by the implementation of the socket() API
*
****************************************************************************/
FAR struct can_conn_s *can_alloc(void);
/****************************************************************************
* Name: can_free()
*
* Description:
* Free a NetLink connection structure that is no longer in use. This
* should be done by the implementation of close().
*
****************************************************************************/
void can_free(FAR struct can_conn_s *conn);
/****************************************************************************
* Name: can_nextconn()
*
* Description:
* Traverse the list of allocated NetLink connections
*
* Assumptions:
* This function is called from NetLink device logic.
*
****************************************************************************/
FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn);
/****************************************************************************
* Name: can_callback
*
* Description:
* Inform the application holding the packet socket of a change in state.
*
* Returned Value:
* OK if packet has been processed, otherwise ERROR.
*
* Assumptions:
* This function is called from network logic at with the network locked.
*
****************************************************************************/
uint16_t can_callback(FAR struct net_driver_s *dev,
FAR struct can_conn_s *conn, uint16_t flags);
/****************************************************************************
* Name: can_datahandler
*
* Description:
* Handle data that is not accepted by the application. This may be called
* either (1) from the data receive logic if it cannot buffer the data, or
* (2) from the CAN event logic is there is no listener in place ready to
* receive the data.
*
* Input Parameters:
* conn - A pointer to the CAN connection structure
* buffer - A pointer to the buffer to be copied to the read-ahead
* buffers
* buflen - The number of bytes to copy to the read-ahead buffer.
*
* Returned Value:
* The number of bytes actually buffered is returned. This will be either
* zero or equal to buflen; partial packets are not buffered.
*
* Assumptions:
* - The caller has checked that CAN_NEWDATA is set in flags and that is no
* other handler available to process the incoming data.
* - Called from network stack logic with the network stack locked
*
****************************************************************************/
uint16_t can_datahandler(FAR struct can_conn_s *conn, FAR uint8_t *buffer,
uint16_t buflen);
/****************************************************************************
* Name: can_recvfrom
*
* Description:
* Implements the socket recvfrom interface pkt_recvfrom() receives
* messages from a socket, and may be used to receive data on a socket
* whether or not it is connection-oriented.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Buffer to receive data
* len Length of buffer
* flags Receive flags
* from Address of source (may be NULL)
* fromlen The length of the address structure
*
* Returned Value:
* On success, returns the number of characters received. If no data is
* available to be received and the peer has performed an orderly shutdown,
* recv() will return 0. Otherwise, on errors, a negated errno value is
* returned (see recvfrom() for the list of appropriate error values).
*
****************************************************************************/
ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
int flags, FAR struct sockaddr *from,
FAR socklen_t *fromlen);
/****************************************************************************
* Name: can_recvmsg
*
* Description:
* recvmsg() receives messages from a socket, and may be used to receive
* data on a socket whether or not it is connection-oriented.
*
* If from is not NULL, and the underlying protocol provides the source
* address, this source address is filled in. The argument 'fromlen'
* initialized to the size of the buffer associated with from, and modified
* on return to indicate the actual size of the address stored there.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* msg Buffer to receive msg
* flags Receive flags (ignored)
*
****************************************************************************/
#ifdef CONFIG_NET_CMSG
ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
int flags);
#endif
/****************************************************************************
* Name: can_poll
*
* Description:
* Poll a CAN connection structure for availability of TX data
*
* Input Parameters:
* dev - The device driver structure to use in the send operation
* conn - The CAN "connection" to poll for TX data
*
* Returned Value:
* None
*
* Assumptions:
* Called from network stack logic with the network stack locked
*
****************************************************************************/
void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn);
/****************************************************************************
* Name: psock_can_send
*
* Description:
* The psock_can_send() call may be used only when the packet socket is in
* a connected state (so that the intended recipient is known).
*
* Input Parameters:
* psock An instance of the internal socket structure.
* buf Data to send
* len Length of data to send
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* a negated errno value is returned. See send() for the complete list
* of return values.
*
****************************************************************************/
struct socket;
ssize_t psock_can_send(FAR struct socket *psock, FAR const void *buf,
size_t len);
/****************************************************************************
* Name: psock_can_sendmsg
*
* Description:
* The psock_can_sendmsg() call may be used only when the packet socket is
* in a connected state (so that the intended recipient is known).
*
* Input Parameters:
* psock An instance of the internal socket structure.
* msg msg to send
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* a negated errno value is returned. See send() for the complete list
* of return values.
*
****************************************************************************/
#ifdef CONFIG_NET_CMSG
ssize_t psock_can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg);
#endif
/****************************************************************************
* Name: can_readahead_signal
*
* Description:
* Read-ahead data has been buffered. Signal all threads waiting for
* read-ahead data to become available.
*
* When read-ahead data becomes available, *all* of the workers waiting
* for read-ahead data will be executed. If there are multiple workers
* waiting for read-ahead data then only the first to execute will get the
* data. Others will need to call can_readahead_notifier_setup() once
* again.
*
* Input Parameters:
* conn - The CAN connection where read-ahead data was just buffered.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_NET_CAN_NOTIFIER
void can_readahead_signal(FAR struct can_conn_s *conn);
#endif
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_NET_CAN */
#endif /* __NET_CAN_CAN_H */

242
net/can/can_callback.c Normal file
View file

@ -0,0 +1,242 @@
/****************************************************************************
* net/pkt/pkt_callback.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
#include <stdint.h>
#include <debug.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/netdev.h>
#include <nuttx/mm/iob.h>
#include "devif/devif.h"
#include "can/can.h"
#ifdef CONFIG_NET_TIMESTAMP
#include <sys/time.h>
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: can_data_event
*
* Description:
* Handle data that is not accepted by the application because there is no
* listener in place ready to receive the data.
*
* Assumptions:
* - The caller has checked that CAN_NEWDATA is set in flags and that is no
* other handler available to process the incoming data.
* - This function must be called with the network locked.
*
****************************************************************************/
static inline uint16_t
can_data_event(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn,
uint16_t flags)
{
uint16_t ret;
FAR uint8_t *buffer = dev->d_appdata;
int buflen = dev->d_len;
uint16_t recvlen;
ret = (flags & ~CAN_NEWDATA);
/* Save as the packet data as in the read-ahead buffer. NOTE that
* partial packets will not be buffered.
*/
recvlen = can_datahandler(conn, buffer, buflen);
if (recvlen < buflen)
{
/* There is no handler to receive new data and there are no free
* read-ahead buffers to retain the data -- drop the packet.
*/
ninfo("Dropped %d bytes\n", dev->d_len);
#ifdef CONFIG_NET_STATISTICS
/* No support CAN net statistics yet */
/* g_netstats.tcp.drop++; */
#endif
}
/* In any event, the new data has now been handled */
dev->d_len = 0;
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: can_callback
*
* Description:
* Inform the application holding the packet socket of a change in state.
*
* Returned Value:
* OK if packet has been processed, otherwise ERROR.
*
* Assumptions:
* This function can be called from an interrupt.
*
****************************************************************************/
uint16_t can_callback(FAR struct net_driver_s *dev,
FAR struct can_conn_s *conn, uint16_t flags)
{
/* Some sanity checking */
if (conn)
{
#ifdef CONFIG_NET_TIMESTAMP
/* TIMESTAMP sockopt is activated, create timestamp and copy to iob */
if (conn->psock->s_timestamp)
{
struct timespec *ts = (struct timespec *)
&dev->d_appdata[dev->d_len];
struct timeval *tv = (struct timeval *)
&dev->d_appdata[dev->d_len];
dev->d_len += sizeof(struct timeval);
clock_systime_timespec(ts);
tv->tv_usec = ts->tv_nsec / 1000;
}
#endif
/* Try to lock the network when successfull send data to the listener */
if (net_trylock() == OK)
{
flags = devif_conn_event(dev, conn, flags, conn->list);
net_unlock();
}
/* Either we did not get the lock or there is no application listening
* If we did not get a lock we store the frame in the read-ahead buffer
*/
if ((flags & CAN_NEWDATA) != 0)
{
/* Data was not handled.. dispose of it appropriately */
flags = can_data_event(dev, conn, flags);
}
}
return flags;
}
/****************************************************************************
* Name: can_datahandler
*
* Description:
* Handle data that is not accepted by the application. This may be called
* either (1) from the data receive logic if it cannot buffer the data, or
* (2) from the CAN event logic is there is no listener in place ready to
* receive the data.
*
* Input Parameters:
* conn - A pointer to the CAN connection structure
* buffer - A pointer to the buffer to be copied to the read-ahead
* buffers
* buflen - The number of bytes to copy to the read-ahead buffer.
*
* Returned Value:
* The number of bytes actually buffered is returned. This will be either
* zero or equal to buflen; partial packets are not buffered.
*
* Assumptions:
* - The caller has checked that CAN_NEWDATA is set in flags and that is no
* other handler available to process the incoming data.
* - This function must be called with the network locked.
*
****************************************************************************/
uint16_t can_datahandler(FAR struct can_conn_s *conn, FAR uint8_t *buffer,
uint16_t buflen)
{
FAR struct iob_s *iob;
int ret;
/* Try to allocate on I/O buffer to start the chain without waiting (and
* throttling as necessary). If we would have to wait, then drop the
* packet.
*/
iob = iob_tryalloc(true, IOBUSER_NET_CAN_READAHEAD);
if (iob == NULL)
{
nerr("ERROR: Failed to create new I/O buffer chain\n");
return 0;
}
/* Copy the new appdata into the I/O buffer chain (without waiting) */
ret = iob_trycopyin(iob, buffer, buflen, 0, true,
IOBUSER_NET_CAN_READAHEAD);
if (ret < 0)
{
/* On a failure, iob_copyin return a negated error value but does
* not free any I/O buffers.
*/
nerr("ERROR: Failed to add data to the I/O buffer chain: %d\n", ret);
iob_free_chain(iob, IOBUSER_NET_CAN_READAHEAD);
return 0;
}
/* Add the new I/O buffer chain to the tail of the read-ahead queue (again
* without waiting).
*/
ret = iob_tryadd_queue(iob, &conn->readahead);
if (ret < 0)
{
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
iob_free_chain(iob, IOBUSER_NET_CAN_READAHEAD);
return 0;
}
#ifdef CONFIG_NET_CAN_NOTIFIER
/* Provide notification(s) that additional CAN read-ahead data is
* available.
*/
can_readahead_signal(conn);
#endif
return buflen;
}
#endif /* CONFIG_NET && CONFIG_NET_CAN */

223
net/can/can_conn.c Normal file
View file

@ -0,0 +1,223 @@
/****************************************************************************
* net/can/can_conn.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <string.h>
#include <queue.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <nuttx/kmalloc.h>
#include <nuttx/semaphore.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/net.h>
#include "utils/utils.h"
#include "can/can.h"
#ifdef CONFIG_NET_CAN
/****************************************************************************
* Private Data
****************************************************************************/
/* The array containing all NetLink connections. */
static struct can_conn_s g_can_connections[CONFIG_CAN_CONNS];
/* A list of all free NetLink connections */
static dq_queue_t g_free_can_connections;
static sem_t g_free_sem;
/* A list of all allocated NetLink connections */
static dq_queue_t g_active_can_connections;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: _can_semtake() and _can_semgive()
*
* Description:
* Take/give semaphore
*
****************************************************************************/
static void _can_semtake(FAR sem_t *sem)
{
net_lockedwait_uninterruptible(sem);
}
static void _can_semgive(FAR sem_t *sem)
{
nxsem_post(sem);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: can_initialize()
*
* Description:
* Initialize the User Socket connection structures. Called once and only
* from the networking layer.
*
****************************************************************************/
void can_initialize(void)
{
int i;
/* Initialize the queues */
dq_init(&g_free_can_connections);
dq_init(&g_active_can_connections);
nxsem_init(&g_free_sem, 0, 1);
for (i = 0; i < CONFIG_CAN_CONNS; i++)
{
FAR struct can_conn_s *conn = &g_can_connections[i];
/* Mark the connection closed and move it to the free list */
memset(conn, 0, sizeof(*conn));
dq_addlast(&conn->node, &g_free_can_connections);
}
}
/****************************************************************************
* Name: can_alloc()
*
* Description:
* Allocate a new, uninitialized NetLink connection structure. This is
* normally something done by the implementation of the socket() API
*
****************************************************************************/
FAR struct can_conn_s *can_alloc(void)
{
FAR struct can_conn_s *conn;
/* The free list is protected by a semaphore (that behaves like a mutex). */
_can_semtake(&g_free_sem);
conn = (FAR struct can_conn_s *)dq_remfirst(&g_free_can_connections);
if (conn != NULL)
{
/* Make sure that the connection is marked as uninitialized */
memset(conn, 0, sizeof(*conn));
/* FIXME SocketCAN default behavior enables loopback */
#ifdef CONFIG_NET_CANPROTO_OPTIONS
/* By default the filter is configured to catch all,
* this is done in commented filter code below:
*
* struct can_filter_t catchall_filter;
* filter.can_id = 0;
* filter.can_mask = 0;
* conn->filters[0] = catchall_filter;
*
* However memset already sets the filter to 0
* therefore we only have to set the filter count to 1
*/
conn->filter_count = 1;
#endif
/* Enqueue the connection into the active list */
dq_addlast(&conn->node, &g_active_can_connections);
}
_can_semgive(&g_free_sem);
return conn;
}
/****************************************************************************
* Name: can_free()
*
* Description:
* Free a NetLink connection structure that is no longer in use. This
* should be done by the implementation of close().
*
****************************************************************************/
void can_free(FAR struct can_conn_s *conn)
{
/* The free list is protected by a semaphore (that behaves like a mutex). */
DEBUGASSERT(conn->crefs == 0);
_can_semtake(&g_free_sem);
/* Remove the connection from the active list */
dq_rem(&conn->node, &g_active_can_connections);
/* Reset structure */
memset(conn, 0, sizeof(*conn));
/* Free the connection */
dq_addlast(&conn->node, &g_free_can_connections);
_can_semgive(&g_free_sem);
}
/****************************************************************************
* Name: can_nextconn()
*
* Description:
* Traverse the list of allocated NetLink connections
*
* Assumptions:
* This function is called from NetLink device logic.
*
****************************************************************************/
FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn)
{
if (conn == NULL)
{
return (FAR struct can_conn_s *)g_active_can_connections.head;
}
else
{
return (FAR struct can_conn_s *)conn->node.flink;
}
}
#endif /* CONFIG_NET_CAN */

220
net/can/can_getsockopt.c Normal file
View file

@ -0,0 +1,220 @@
/****************************************************************************
* net/can/can_setsockopt.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/time.h>
#include <stdint.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <netpacket/can.h>
#include <nuttx/net/net.h>
#include <nuttx/net/can.h>
#include "socket/socket.h"
#include "utils/utils.h"
#include "can/can.h"
#ifdef CONFIG_NET_CANPROTO_OPTIONS
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: can_getsockopt
*
* Description:
* can_getsockopt() retrieves the value for the option specified by the
* 'option' argument for the socket specified by the 'psock' argument. If
* the size of the option value is greater than 'value_len', the value
* stored in the object pointed to by the 'value' argument will be silently
* truncated. Otherwise, the length pointed to by the 'value_len' argument
* will be modified to indicate the actual length of the 'value'.
*
* See <sys/socket.h> a complete list of values for the socket-level
* 'option' argument. Protocol-specific options are are protocol specific
* header files (such as netpacket/can.h for the case of the CAN protocol).
*
* Input Parameters:
* psock Socket structure of the socket to query
* level Protocol level to set the option
* option identifies the option to get
* value Points to the argument value
* value_len The length of the argument value
*
* Returned Value:
* Returns zero (OK) on success. On failure, it returns a negated errno
* value to indicate the nature of the error. See psock_getsockopt() for
* the complete list of appropriate return error codes.
*
****************************************************************************/
int can_getsockopt(FAR struct socket *psock, int option,
FAR void *value, FAR socklen_t *value_len)
{
FAR struct can_conn_s *conn;
int ret;
DEBUGASSERT(psock != NULL && value != NULL && value_len != NULL &&
psock->s_conn != NULL);
conn = (FAR struct can_conn_s *)psock->s_conn;
if (psock->s_type != SOCK_RAW)
{
nerr("ERROR: Not a RAW CAN socket\n");
return -ENOTCONN;
}
switch (option)
{
case CAN_RAW_FILTER:
if (*value_len % sizeof(struct can_filter) != 0)
{
ret = -EINVAL;
}
else if (*value_len > CONFIG_NET_CAN_RAW_FILTER_MAX *
sizeof(struct can_filter))
{
ret = -EINVAL;
}
else
{
int count = conn->filter_count;
if (*value_len < count * sizeof(struct can_filter))
{
count = *value_len / sizeof(struct can_filter);
}
else
{
*value_len = count * sizeof(struct can_filter);
}
for (int i = 0; i < count; i++)
{
((struct can_filter *)value)[i] = conn->filters[i];
}
ret = OK;
}
break;
case CAN_RAW_ERR_FILTER:
break;
case CAN_RAW_LOOPBACK:
if (*value_len < sizeof(conn->loopback))
{
/* REVISIT: POSIX says that we should truncate the value if it
* is larger than value_len. That just doesn't make sense
* to me in this case.
*/
ret = -EINVAL;
}
else
{
FAR int *loopback = (FAR int32_t *)value;
*loopback = conn->loopback;
*value_len = sizeof(conn->loopback);
ret = OK;
}
break;
case CAN_RAW_RECV_OWN_MSGS:
if (*value_len < sizeof(conn->recv_own_msgs))
{
/* REVISIT: POSIX says that we should truncate the value if it
* is larger than value_len. That just doesn't make sense
* to me in this case.
*/
ret = -EINVAL;
}
else
{
FAR int *recv_own_msgs = (FAR int32_t *)value;
*recv_own_msgs = conn->recv_own_msgs;
*value_len = sizeof(conn->recv_own_msgs);
ret = OK;
}
break;
case CAN_RAW_FD_FRAMES:
if (*value_len < sizeof(conn->fd_frames))
{
/* REVISIT: POSIX says that we should truncate the value if it
* is larger than value_len. That just doesn't make sense
* to me in this case.
*/
ret = -EINVAL;
}
else
{
FAR int *fd_frames = (FAR int32_t *)value;
*fd_frames = conn->fd_frames;
*value_len = sizeof(conn->fd_frames);
ret = OK;
}
break;
case CAN_RAW_JOIN_FILTERS:
break;
#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
case CAN_RAW_TX_DEADLINE:
if (*value_len < sizeof(conn->tx_deadline))
{
/* REVISIT: POSIX says that we should truncate the value if it
* is larger than value_len. That just doesn't make sense
* to me in this case.
*/
ret = -EINVAL;
}
else
{
FAR int *tx_deadline = (FAR int32_t *)value;
*tx_deadline = conn->tx_deadline;
*value_len = sizeof(conn->tx_deadline);
ret = OK;
}
break;
#endif
default:
nerr("ERROR: Unrecognized RAW CAN socket option: %d\n", option);
ret = -ENOPROTOOPT;
break;
}
return ret;
}
#endif /* CONFIG_NET_CANPROTO_OPTIONS */

204
net/can/can_input.c Normal file
View file

@ -0,0 +1,204 @@
/****************************************************************************
* net/can/can_input.c
* Handling incoming packet input
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
#include <errno.h>
#include <debug.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/can.h>
#include "devif/devif.h"
#include "can/can.h"
/****************************************************************************
* Public Data
****************************************************************************/
const uint8_t can_dlc_to_len[16] =
{
0,
1,
2,
3,
4,
5,
6,
7,
8,
12,
16,
20,
24,
32,
48,
64,
};
const uint8_t len_to_can_dlc[65] =
{
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
9,
9,
9,
10,
10,
10,
10,
11,
11,
11,
11,
12,
12,
12,
12,
13,
13,
13,
13,
13,
13,
13,
13,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: can_input
*
* Description:
* Handle incoming packet input
*
* Input Parameters:
* dev - The device driver structure containing the received packet
*
* Returned Value:
* OK The packet has been processed and can be deleted
* -EAGAIN There is a matching connection, but could not dispatch the packet
* yet. Useful when a packet arrives before a recv call is in
* place.
*
* Assumptions:
* This function can be called from an interrupt.
*
****************************************************************************/
int can_input(struct net_driver_s *dev)
{
FAR struct can_conn_s *conn = NULL;
int ret = OK;
do
{
/* FIXME Support for multiple sockets??? */
conn = can_nextconn(conn);
}
while (conn && conn->dev != 0 && dev != conn->dev);
if (conn)
{
uint16_t flags;
/* Setup for the application callback */
dev->d_appdata = dev->d_buf;
dev->d_sndlen = 0;
/* Perform the application callback */
flags = can_callback(dev, conn, CAN_NEWDATA);
/* If the operation was successful, the CAN_NEWDATA flag is removed
* and thus the packet can be deleted (OK will be returned).
*/
if ((flags & CAN_NEWDATA) != 0)
{
/* No.. the packet was not processed now. Return -EAGAIN so
* that the driver may retry again later. We still need to
* set d_len to zero so that the driver is aware that there
* is nothing to be sent.
*/
nwarn("WARNING: Packet not processed\n");
ret = -EAGAIN;
}
}
else
{
ninfo("No CAN listener\n");
}
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_CAN */

83
net/can/can_notifier.c Normal file
View file

@ -0,0 +1,83 @@
/****************************************************************************
* net/can/can_notifier.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <assert.h>
#include <nuttx/wqueue.h>
#include "can/can.h"
#ifdef CONFIG_NET_CAN_NOTIFIER
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: can_readahead_signal
*
* Description:
* Read-ahead data has been buffered. Signal all threads waiting for
* read-ahead data to become available.
*
* When read-ahead data becomes available, *all* of the workers waiting
* for read-ahead data will be executed. If there are multiple workers
* waiting for read-ahead data then only the first to execute will get the
* data. Others will need to call can_readahead_notifier_setup() once
* again.
*
* Input Parameters:
* conn - The CAN connection where read-ahead data was just buffered.
*
* Returned Value:
* None.
*
****************************************************************************/
void can_readahead_signal(FAR struct can_conn_s *conn)
{
/* This is just a simple wrapper around work_notifier_signal(). */
work_notifier_signal(WORK_CAN_READAHEAD, conn);
}
#endif /* CONFIG_NET_CAN_NOTIFIER */

88
net/can/can_poll.c Normal file
View file

@ -0,0 +1,88 @@
/****************************************************************************
* net/pkt/pkt_poll.c
* Poll for the availability of packet TX data
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
#include <debug.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/netdev.h>
#include "devif/devif.h"
#include "can/can.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: can_poll
*
* Description:
* Poll a packet "connection" structure for availability of TX data
*
* Input Parameters:
* dev - The device driver structure to use in the send operation
* conn - The packet "connection" to poll for TX data
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn)
{
/* Verify that the packet connection is valid */
if (conn != NULL)
{
/* Setup for the application callback */
dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev)];
dev->d_len = 0;
dev->d_sndlen = 0;
/* Perform the application callback */
can_callback(dev, conn, CAN_POLL);
/* Check if the application has data to send */
if (dev->d_sndlen > 0)
{
return;
}
}
/* Make sure that d_len is zero meaning that there is nothing to be sent */
dev->d_len = 0;
}
#endif /* CONFIG_NET && CONFIG_NET_CAN */

838
net/can/can_recvfrom.c Normal file
View file

@ -0,0 +1,838 @@
/****************************************************************************
* net/can/can_recvfrom.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#ifdef CONFIG_NET_CAN
#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <assert.h>
#include <arch/irq.h>
#include <nuttx/semaphore.h>
#include <nuttx/net/net.h>
#include <nuttx/net/netdev.h>
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "can/can.h"
#include "socket/socket.h"
#include <netpacket/packet.h>
#ifdef CONFIG_NET_TIMESTAMP
#include <sys/time.h>
#endif
/****************************************************************************
* Private Types
****************************************************************************/
struct can_recvfrom_s
{
FAR struct socket *pr_sock; /* The parent socket structure */
FAR struct devif_callback_s *pr_cb; /* Reference to callback instance */
sem_t pr_sem; /* Semaphore signals recv completion */
size_t pr_buflen; /* Length of receive buffer */
FAR uint8_t *pr_buffer; /* Pointer to receive buffer */
ssize_t pr_recvlen; /* The received length */
#ifdef CONFIG_NET_CMSG
size_t pr_msglen; /* Length of msg buffer */
FAR uint8_t *pr_msgbuf; /* Pointer to msg buffer */
#endif
int pr_result; /* Success:OK, failure:negated errno */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: can_add_recvlen
*
* Description:
* Update information about space available for new data and update size
* of data in buffer, This logic accounts for the case where
* recvfrom_udpreadahead() sets state.pr_recvlen == -1 .
*
* Input Parameters:
* pstate recvfrom state structure
* recvlen size of new data appended to buffer
*
* Returned Value:
* None
*
****************************************************************************/
static inline void can_add_recvlen(FAR struct can_recvfrom_s *pstate,
size_t recvlen)
{
if (pstate->pr_recvlen < 0)
{
pstate->pr_recvlen = 0;
}
pstate->pr_recvlen += recvlen;
pstate->pr_buffer += recvlen;
pstate->pr_buflen -= recvlen;
}
/****************************************************************************
* Name: can_recvfrom_newdata
*
* Description:
* Copy the read data from the packet
*
* Input Parameters:
* dev The structure of the network driver that caused the event.
* pstate recvfrom state structure
*
* Returned Value:
* None.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static size_t can_recvfrom_newdata(FAR struct net_driver_s *dev,
FAR struct can_recvfrom_s *pstate)
{
size_t recvlen;
if (dev->d_len > pstate->pr_buflen)
{
recvlen = pstate->pr_buflen;
}
else
{
recvlen = dev->d_len;
}
/* Copy the new packet data into the user buffer */
memcpy(pstate->pr_buffer, dev->d_buf, recvlen);
/* Update the accumulated size of the data read */
can_add_recvlen(pstate, recvlen);
return recvlen;
}
/****************************************************************************
* Name: can_newdata
*
* Description:
* Copy the read data from the packet
*
* Input Parameters:
* dev The structure of the network driver that generated the event
* pstate recvfrom state structure
*
* Returned Value:
* None.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline void can_newdata(FAR struct net_driver_s *dev,
FAR struct can_recvfrom_s *pstate)
{
/* Take as much data from the packet as we can */
size_t recvlen = can_recvfrom_newdata(dev, pstate);
/* If there is more data left in the packet that we could not buffer, then
* add it to the read-ahead buffers.
*/
if (recvlen < dev->d_len)
{
FAR struct can_conn_s *conn =
(FAR struct can_conn_s *)pstate->pr_sock->s_conn;
FAR uint8_t *buffer = (FAR uint8_t *)dev->d_appdata + recvlen;
uint16_t buflen = dev->d_len - recvlen;
#ifdef CONFIG_DEBUG_NET
uint16_t nsaved;
nsaved = can_datahandler(conn, buffer, buflen);
#else
can_datahandler(conn, buffer, buflen);
#endif
/* There are complicated buffering issues that are not addressed fully
* here. For example, what if up_datahandler() cannot buffer the
* remainder of the packet? In that case, the data will be dropped but
* still ACKed. Therefore it would not be resent.
*
* This is probably not an issue here because we only get here if the
* read-ahead buffers are empty and there would have to be something
* serioulsy wrong with the configuration not to be able to buffer a
* partial packet in this context.
*/
#ifdef CONFIG_DEBUG_NET
if (nsaved < buflen)
{
nerr("ERROR: packet data not saved (%d bytes)\n", buflen - nsaved);
}
#endif
}
/* Indicate no data in the buffer */
dev->d_len = 0;
}
/****************************************************************************
* Name: can_readahead
*
* Description:
* Copy the read-ahead data from the packet
*
* Input Parameters:
* pstate recvfrom state structure
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline int can_readahead(struct can_recvfrom_s *pstate)
{
FAR struct can_conn_s *conn =
(FAR struct can_conn_s *) pstate->pr_sock->s_conn;
FAR struct iob_s *iob;
int recvlen;
/* Check there is any CAN data already buffered in a read-ahead
* buffer.
*/
pstate->pr_recvlen = -1;
if ((iob = iob_peek_queue(&conn->readahead)) != NULL &&
pstate->pr_buflen > 0)
{
DEBUGASSERT(iob->io_pktlen > 0);
/* Transfer that buffered data from the I/O buffer chain into
* the user buffer.
*/
recvlen = iob_copyout(pstate->pr_buffer, iob, pstate->pr_buflen, 0);
/* If we took all of the data from the I/O buffer chain is empty, then
* release it. If there is still data available in the I/O buffer
* chain, then just trim the data that we have taken from the
* beginning of the I/O buffer chain.
*/
if (recvlen >= iob->io_pktlen)
{
FAR struct iob_s *tmp;
/* Remove the I/O buffer chain from the head of the read-ahead
* buffer queue.
*/
tmp = iob_remove_queue(&conn->readahead);
DEBUGASSERT(tmp == iob);
UNUSED(tmp);
/* And free the I/O buffer chain */
iob_free_chain(iob, IOBUSER_NET_CAN_READAHEAD);
}
else
{
/* The bytes that we have received from the head of the I/O
* buffer chain (probably changing the head of the I/O
* buffer queue).
*/
iob_trimhead_queue(&conn->readahead, recvlen,
IOBUSER_NET_CAN_READAHEAD);
}
/* do not pass frames with DLC > 8 to a legacy socket */
#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD)
if (!conn->fd_frames)
#endif
{
if (recvlen > sizeof(struct can_frame))
{
return 0;
}
}
return recvlen;
}
return 0;
}
/****************************************************************************
* Name: can_readahead
*
* Description:
* Copy the read-ahead data from the packet
*
* Input Parameters:
* pstate recvfrom state structure
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_TIMESTAMP
static inline int can_readahead_timestamp(struct can_conn_s *conn,
FAR uint8_t *buffer)
{
FAR struct iob_s *iob;
int recvlen;
if ((iob = iob_peek_queue(&conn->readahead)) != NULL)
{
DEBUGASSERT(iob->io_pktlen > 0);
/* Transfer that buffered data from the I/O buffer chain into
* the user buffer.
*/
recvlen = iob_copyout(buffer, iob, sizeof(struct timeval), 0);
/* If we took all of the data from the I/O buffer chain is empty, then
* release it. If there is still data available in the I/O buffer
* chain, then just trim the data that we have taken from the
* beginning of the I/O buffer chain.
*/
if (recvlen >= iob->io_pktlen)
{
FAR struct iob_s *tmp;
/* Remove the I/O buffer chain from the head of the read-ahead
* buffer queue.
*/
tmp = iob_remove_queue(&conn->readahead);
DEBUGASSERT(tmp == iob);
UNUSED(tmp);
/* And free the I/O buffer chain */
iob_free_chain(iob, IOBUSER_NET_CAN_READAHEAD);
}
else
{
/* The bytes that we have received from the head of the I/O
* buffer chain (probably changing the head of the I/O
* buffer queue).
*/
iob_trimhead_queue(&conn->readahead, recvlen,
IOBUSER_NET_CAN_READAHEAD);
}
return recvlen;
}
return 0;
}
#endif
#ifdef CONFIG_NET_CANPROTO_OPTIONS
static int can_recv_filter(struct can_conn_s *conn, canid_t id)
{
for (int i = 0; i < conn->filter_count; i++)
{
if (conn->filters[i].can_id & CAN_INV_FILTER)
{
if ((id & conn->filters[i].can_mask) !=
((conn->filters[i].can_id & ~CAN_INV_FILTER) &
conn->filters[i].can_mask))
{
return 1;
}
}
else
{
if ((id & conn->filters[i].can_mask) ==
(conn->filters[i].can_id & conn->filters[i].can_mask))
{
return 1;
}
}
}
return 0;
}
#endif
static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
struct can_recvfrom_s *pstate = (struct can_recvfrom_s *)pvpriv;
struct can_conn_s *conn = (struct can_conn_s *)pstate->pr_sock->s_conn;
/* 'priv' might be null in some race conditions (?) */
if (pstate)
{
if ((flags & CAN_NEWDATA) != 0)
{
/* If a new packet is available, check receive filters
* when is valid then complete the read action.
*/
#ifdef CONFIG_NET_CANPROTO_OPTIONS
if (can_recv_filter(conn, (canid_t) *dev->d_appdata) == 0)
{
flags &= ~CAN_NEWDATA;
return flags;
}
#endif
/* do not pass frames with DLC > 8 to a legacy socket */
#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD)
if (!conn->fd_frames)
#endif
{
if (dev->d_len > sizeof(struct can_frame))
{
/* DO WE NEED TO CLEAR FLAGS?? */
flags &= ~CAN_NEWDATA;
return flags;
}
}
/* Copy the packet */
can_newdata(dev, pstate);
#ifdef CONFIG_NET_TIMESTAMP
if (pstate->pr_sock->s_timestamp)
{
if (pstate->pr_msglen == sizeof(struct timeval))
{
can_readahead_timestamp(conn, pstate->pr_msgbuf);
}
else
{
/* We still have to consume the data
* otherwise IOB gets full
*/
uint8_t dummy_buf[sizeof(struct timeval)];
can_readahead_timestamp(conn, (uint8_t *)&dummy_buf);
}
}
#endif
/* We are finished. */
/* Don't allow any further call backs. */
pstate->pr_cb->flags = 0;
pstate->pr_cb->priv = NULL;
pstate->pr_cb->event = NULL;
/* indicate that the data has been consumed */
flags &= ~CAN_NEWDATA;
/* Wake up the waiting thread, returning the number of bytes
* actually read.
*/
nxsem_post(&pstate->pr_sem);
}
}
return flags;
}
/****************************************************************************
* Name: can_recvfrom_result
*
* Description:
* Evaluate the result of the recv operations
*
* Input Parameters:
* result The result of the net_lockedwait operation (may indicate EINTR)
* pstate A pointer to the state structure to be initialized
*
* Returned Value:
* The result of the recv operation with errno set appropriately
*
* Assumptions:
*
****************************************************************************/
static ssize_t can_recvfrom_result(int result,
FAR struct can_recvfrom_s *pstate)
{
/* Check for a error/timeout detected by the event handler. Errors are
* signaled by negative errno values for the rcv length
*/
if (pstate->pr_result < 0)
{
/* This might return EAGAIN on a timeout */
return pstate->pr_result;
}
/* If net_lockedwait failed, then we were probably reawakened by a signal.
* In this case, net_lockedwait will have returned negated errno
* appropriately.
*/
if (result < 0)
{
return result;
}
return pstate->pr_recvlen;
}
/****************************************************************************
* Name: can_recvfrom
*
* Description:
* recvfrom() receives messages from a socket, and may be used to receive
* data on a socket whether or not it is connection-oriented.
*
* If from is not NULL, and the underlying protocol provides the source
* address, this source address is filled in. The argument 'fromlen'
* initialized to the size of the buffer associated with from, and modified
* on return to indicate the actual size of the address stored there.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Buffer to receive data
* len Length of buffer
* flags Receive flags (ignored)
* from Address of source (may be NULL)
* fromlen The length of the address structure
*
****************************************************************************/
ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf,
size_t len, int flags,
FAR struct sockaddr *from,
FAR socklen_t *fromlen)
{
FAR struct can_conn_s *conn;
FAR struct net_driver_s *dev;
struct can_recvfrom_s state;
int ret;
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
DEBUGASSERT(from == NULL ||
(fromlen != NULL && *fromlen >= sizeof(struct sockaddr_can)));
conn = (FAR struct can_conn_s *)psock->s_conn;
if (psock->s_type != SOCK_RAW)
{
nerr("ERROR: Unsupported socket type: %d\n", psock->s_type);
ret = -ENOSYS;
}
net_lock();
/* Initialize the state structure. */
memset(&state, 0, sizeof(struct can_recvfrom_s));
/* This semaphore is used for signaling and, hence, should not have
* priority inheritance enabled.
*/
nxsem_init(&state.pr_sem, 0, 0); /* Doesn't really fail */
nxsem_set_protocol(&state.pr_sem, SEM_PRIO_NONE);
state.pr_buflen = len;
state.pr_buffer = buf;
state.pr_sock = psock;
/* Handle any any CAN data already buffered in a read-ahead buffer. NOTE
* that there may be read-ahead data to be retrieved even after the
* socket has been disconnected.
*/
ret = can_readahead(&state);
if (ret > 0)
{
goto errout_with_state;
}
ret = state.pr_recvlen;
/* Handle non-blocking CAN sockets */
if (_SS_ISNONBLOCK(psock->s_flags) || (flags & MSG_DONTWAIT) != 0)
{
/* Return the number of bytes read from the read-ahead buffer if
* something was received (already in 'ret'); EAGAIN if not.
*/
if (ret < 0)
{
/* Nothing was received */
ret = -EAGAIN;
goto errout_with_state;
}
}
/* Get the device driver that will service this transfer */
dev = conn->dev;
if (dev == NULL)
{
ret = -ENODEV;
goto errout_with_state;
}
/* Set up the callback in the connection */
state.pr_cb = can_callback_alloc(dev, conn);
if (state.pr_cb)
{
state.pr_cb->flags = (CAN_NEWDATA | CAN_POLL);
state.pr_cb->priv = (FAR void *)&state;
state.pr_cb->event = can_recvfrom_eventhandler;
/* Wait for either the receive to complete or for an error/timeout to
* occur. NOTES: (1) net_lockedwait will also terminate if a signal
* is received, (2) the network is locked! It will be un-locked while
* the task sleeps and automatically re-locked when the task restarts.
*/
ret = net_lockedwait(&state.pr_sem);
/* Make sure that no further events are processed */
can_callback_free(dev, conn, state.pr_cb);
ret = can_recvfrom_result(ret, &state);
}
else
{
ret = -EBUSY;
}
errout_with_state:
net_unlock();
nxsem_destroy(&state.pr_sem);
return ret;
}
/****************************************************************************
* Name: can_recvmsg
*
* Description:
* recvmsg() receives messages from a socket, and may be used to receive
* data on a socket whether or not it is connection-oriented.
*
* If from is not NULL, and the underlying protocol provides the source
* address, this source address is filled in. The argument 'fromlen'
* initialized to the size of the buffer associated with from, and modified
* on return to indicate the actual size of the address stored there.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* msg Buffer to receive msg
* flags Receive flags (ignored)
*
****************************************************************************/
#ifdef CONFIG_NET_CMSG
ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
int flags)
{
FAR struct can_conn_s *conn;
FAR struct net_driver_s *dev;
struct can_recvfrom_s state;
int ret;
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && msg != NULL);
conn = (FAR struct can_conn_s *)psock->s_conn;
if (psock->s_type != SOCK_RAW)
{
nerr("ERROR: Unsupported socket type: %d\n", psock->s_type);
ret = -ENOSYS;
}
net_lock();
/* Initialize the state structure. */
memset(&state, 0, sizeof(struct can_recvfrom_s));
/* This semaphore is used for signaling and, hence, should not have
* priority inheritance enabled.
*/
nxsem_init(&state.pr_sem, 0, 0); /* Doesn't really fail */
nxsem_set_protocol(&state.pr_sem, SEM_PRIO_NONE);
state.pr_buflen = msg->msg_iov->iov_len;
state.pr_buffer = msg->msg_iov->iov_base;
#ifdef CONFIG_NET_TIMESTAMP
if (psock->s_timestamp && msg->msg_controllen >=
(sizeof(struct cmsghdr) + sizeof(struct timeval)))
{
struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
state.pr_msglen = sizeof(struct timeval);
state.pr_msgbuf = CMSG_DATA(cmsg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SO_TIMESTAMP;
cmsg->cmsg_len = state.pr_msglen;
msg->msg_controllen = sizeof(struct cmsghdr) + sizeof(struct timeval);
}
else
{
/* Expected behavior is that the msg_controllen becomes 0,
* otherwise CMSG_NXTHDR will go into a infinite loop
*/
msg->msg_controllen = 0;
}
#endif
state.pr_sock = psock;
/* Handle any any CAN data already buffered in a read-ahead buffer. NOTE
* that there may be read-ahead data to be retrieved even after the
* socket has been disconnected.
*/
ret = can_readahead(&state);
if (ret > 0)
{
#ifdef CONFIG_NET_TIMESTAMP
if (psock->s_timestamp)
{
if (state.pr_msglen == sizeof(struct timeval))
{
can_readahead_timestamp(conn, state.pr_msgbuf);
}
else
{
/* We still have to consume the data otherwise IOB gets full */
uint8_t dummy_buf[sizeof(struct timeval)];
can_readahead_timestamp(conn, (uint8_t *)&dummy_buf);
}
}
#endif
goto errout_with_state;
}
ret = state.pr_recvlen;
/* Handle non-blocking CAN sockets */
if (_SS_ISNONBLOCK(psock->s_flags) || (flags & MSG_DONTWAIT) != 0)
{
/* Return the number of bytes read from the read-ahead buffer if
* something was received (already in 'ret'); EAGAIN if not.
*/
if (ret < 0)
{
/* Nothing was received */
ret = -EAGAIN;
goto errout_with_state;
}
}
/* Get the device driver that will service this transfer */
dev = conn->dev;
if (dev == NULL)
{
ret = -ENODEV;
goto errout_with_state;
}
/* Set up the callback in the connection */
state.pr_cb = can_callback_alloc(dev, conn);
if (state.pr_cb)
{
state.pr_cb->flags = (CAN_NEWDATA | CAN_POLL);
state.pr_cb->priv = (FAR void *)&state;
state.pr_cb->event = can_recvfrom_eventhandler;
/* Wait for either the receive to complete or for an error/timeout to
* occur. NOTES: (1) net_lockedwait will also terminate if a signal
* is received, (2) the network is locked! It will be un-locked while
* the task sleeps and automatically re-locked when the task restarts.
*/
ret = net_lockedwait(&state.pr_sem);
/* Make sure that no further events are processed */
can_callback_free(dev, conn, state.pr_cb);
ret = can_recvfrom_result(ret, &state);
}
else
{
ret = -EBUSY;
}
errout_with_state:
net_unlock();
nxsem_destroy(&state.pr_sem);
return ret;
}
#endif
#endif /* CONFIG_NET_CAN */

441
net/can/can_send.c Normal file
View file

@ -0,0 +1,441 @@
/****************************************************************************
* net/can/can_send.c
*
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_CAN)
#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <nuttx/semaphore.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/net.h>
#include <nuttx/net/ip.h>
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "socket/socket.h"
#include "can/can.h"
#ifdef CONFIG_NET_CMSG
#include <sys/time.h>
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure holds the state of the send operation until it can be
* operated upon by the event handler.
*/
struct send_s
{
FAR struct socket *snd_sock; /* Points to the parent socket structure */
FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
sem_t snd_sem; /* Used to wake up the waiting thread */
FAR const uint8_t *snd_buffer; /* Points to the buffer of data to send */
size_t snd_buflen; /* Number of bytes in the buffer to send */
#ifdef CONFIG_NET_CMSG
size_t pr_msglen; /* Length of msg buffer */
FAR uint8_t *pr_msgbuf; /* Pointer to msg buffer */
#endif
ssize_t snd_sent; /* The number of bytes sent */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: psock_send_eventhandler
****************************************************************************/
static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;
if (pstate)
{
/* Check if the outgoing packet is available. It may have been claimed
* by a send event handler serving a different thread -OR- if the
* output buffer currently contains unprocessed incoming data. In
* these cases we will just have to wait for the next polling cycle.
*/
if (dev->d_sndlen > 0 || (flags & CAN_NEWDATA) != 0)
{
/* Another thread has beat us sending data or the buffer is busy,
* Check for a timeout. If not timed out, wait for the next
* polling cycle and check again.
*/
/* No timeout. Just wait for the next polling cycle */
return flags;
}
/* It looks like we are good to send the data */
else
{
/* Copy the packet data into the device packet buffer and send it */
devif_can_send(dev, pstate->snd_buffer, pstate->snd_buflen);
pstate->snd_sent = pstate->snd_buflen;
#ifdef CONFIG_NET_CMSG
if (pstate->pr_msglen > 0) /* concat cmsg data after packet */
{
memcpy(dev->d_buf + pstate->snd_buflen, pstate->pr_msgbuf,
pstate->pr_msglen);
dev->d_sndlen = pstate->snd_buflen + pstate->pr_msglen;
}
#endif
}
/* Don't allow any further call backs. */
pstate->snd_cb->flags = 0;
pstate->snd_cb->priv = NULL;
pstate->snd_cb->event = NULL;
/* Wake up the waiting thread */
nxsem_post(&pstate->snd_sem);
}
return flags;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: psock_can_send
*
* Description:
* The psock_can_send() call may be used only when the packet socket is in
* a connected state (so that the intended recipient is known).
*
* Input Parameters:
* psock An instance of the internal socket structure.
* buf Data to send
* len Length of data to send
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* a negated errno value is retruend. See send() for the complete list
* of return values.
*
****************************************************************************/
ssize_t psock_can_send(FAR struct socket *psock, FAR const void *buf,
size_t len)
{
FAR struct net_driver_s *dev;
FAR struct can_conn_s *conn;
struct send_s state;
int ret = OK;
conn = (FAR struct can_conn_s *)psock->s_conn;
/* Verify that the sockfd corresponds to valid, allocated socket */
if (!psock || psock->s_crefs <= 0)
{
return -EBADF;
}
/* Get the device driver that will service this transfer */
dev = conn->dev;
if (dev == NULL)
{
return -ENODEV;
}
#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD)
if (conn->fd_frames)
{
if (len != CANFD_MTU && len != CAN_MTU)
{
return -EINVAL;
}
}
#endif
else
{
if (len != CAN_MTU)
{
return -EINVAL;
}
}
/* Perform the send operation */
/* Initialize the state structure. This is done with the network locked
* because we don't want anything to happen until we are ready.
*/
net_lock();
memset(&state, 0, sizeof(struct send_s));
/* This semaphore is used for signaling and, hence, should not have
* priority inheritance enabled.
*/
nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
nxsem_set_protocol(&state.snd_sem, SEM_PRIO_NONE);
state.snd_sock = psock; /* Socket descriptor to use */
state.snd_buflen = len; /* Number of bytes to send */
state.snd_buffer = buf; /* Buffer to send from */
/* Allocate resource to receive a callback */
state.snd_cb = can_callback_alloc(dev, conn);
if (state.snd_cb)
{
/* Set up the callback in the connection */
state.snd_cb->flags = CAN_POLL;
state.snd_cb->priv = (FAR void *)&state;
state.snd_cb->event = psock_send_eventhandler;
/* Notify the device driver that new TX data is available. */
netdev_txnotify_dev(dev);
/* Wait for the send to complete or an error to occur.
* net_lockedwait will also terminate if a signal is received.
*/
ret = net_lockedwait(&state.snd_sem);
/* Make sure that no further events are processed */
can_callback_free(dev, conn, state.snd_cb);
}
nxsem_destroy(&state.snd_sem);
net_unlock();
/* Check for a errors, Errors are signalled by negative errno values
* for the send length
*/
if (state.snd_sent < 0)
{
return state.snd_sent;
}
/* If net_lockedwait failed, then we were probably reawakened by a signal.
* In this case, net_lockedwait will have returned negated errno
* appropriately.
*/
if (ret < 0)
{
return ret;
}
/* Return the number of bytes actually sent */
return state.snd_sent;
}
/****************************************************************************
* Name: psock_can_sendmsg
*
* Description:
* The psock_can_sendmsg() call may be used only when the packet socket is
* in a connected state (so that the intended recipient is known).
*
* Input Parameters:
* psock An instance of the internal socket structure.
* msg msg to send
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* a negated errno value is retruend. See send() for the complete list
* of return values.
*
****************************************************************************/
ssize_t psock_can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg)
{
FAR struct net_driver_s *dev;
FAR struct can_conn_s *conn;
struct send_s state;
int ret = OK;
conn = (FAR struct can_conn_s *)psock->s_conn;
/* Verify that the sockfd corresponds to valid, allocated socket */
if (!psock || psock->s_crefs <= 0)
{
return -EBADF;
}
/* Get the device driver that will service this transfer */
dev = conn->dev;
if (dev == NULL)
{
return -ENODEV;
}
#if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD)
if (conn->fd_frames)
{
if (msg->msg_iov->iov_len != CANFD_MTU
&& msg->msg_iov->iov_len != CAN_MTU)
{
return -EINVAL;
}
}
else
#endif
{
if (msg->msg_iov->iov_len != CAN_MTU)
{
return -EINVAL;
}
}
/* Perform the send operation */
/* Initialize the state structure. This is done with the network locked
* because we don't want anything to happen until we are ready.
*/
net_lock();
memset(&state, 0, sizeof(struct send_s));
/* This semaphore is used for signaling and, hence, should not have
* priority inheritance enabled.
*/
nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
nxsem_set_protocol(&state.snd_sem, SEM_PRIO_NONE);
state.snd_sock = psock; /* Socket descriptor */
state.snd_buflen = msg->msg_iov->iov_len; /* bytes to send */
state.snd_buffer = msg->msg_iov->iov_base; /* Buffer to send from */
#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
if (msg->msg_controllen > sizeof(struct cmsghdr))
{
struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
if (conn->tx_deadline && cmsg->cmsg_level == SOL_CAN_RAW
&& cmsg->cmsg_type == CAN_RAW_TX_DEADLINE
&& cmsg->cmsg_len == sizeof(struct timeval))
{
state.pr_msgbuf = CMSG_DATA(cmsg); /* Buffer to cmsg data */
state.pr_msglen = cmsg->cmsg_len; /* len of cmsg data */
}
}
#endif
/* Allocate resource to receive a callback */
state.snd_cb = can_callback_alloc(dev, conn);
if (state.snd_cb)
{
/* Set up the callback in the connection */
state.snd_cb->flags = CAN_POLL;
state.snd_cb->priv = (FAR void *)&state;
state.snd_cb->event = psock_send_eventhandler;
/* Notify the device driver that new TX data is available. */
netdev_txnotify_dev(dev);
/* Wait for the send to complete or an error to occur.
* net_lockedwait will also terminate if a signal is received.
*/
ret = net_lockedwait(&state.snd_sem);
/* Make sure that no further events are processed */
can_callback_free(dev, conn, state.snd_cb);
}
nxsem_destroy(&state.snd_sem);
net_unlock();
/* Check for a errors, Errors are signalled by negative errno values
* for the send length
*/
if (state.snd_sent < 0)
{
return state.snd_sent;
}
/* If net_lockedwait failed, then we were probably reawakened by a signal.
* In this case, net_lockedwait will have returned negated errno
* appropriately.
*/
if (ret < 0)
{
return ret;
}
/* Return the number of bytes actually sent */
return state.snd_sent;
}
#endif /* CONFIG_NET && CONFIG_NET_CAN */

177
net/can/can_setsockopt.c Normal file
View file

@ -0,0 +1,177 @@
/****************************************************************************
* net/can/can_setsockopt.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/time.h>
#include <stdint.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <netpacket/can.h>
#include <nuttx/net/net.h>
#include <nuttx/net/can.h>
#include "socket/socket.h"
#include "utils/utils.h"
#include "can/can.h"
#ifdef CONFIG_NET_CANPROTO_OPTIONS
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: can_setsockopt
*
* Description:
* can_setsockopt() sets the CAN-protocol option specified by the
* 'option' argument to the value pointed to by the 'value' argument for
* the socket specified by the 'psock' argument.
*
* See <netinet/can.h> for the a complete list of values of CAN protocol
* options.
*
* Input Parameters:
* psock Socket structure of socket to operate on
* option identifies the option to set
* value Points to the argument value
* value_len The length of the argument value
*
* Returned Value:
* Returns zero (OK) on success. On failure, it returns a negated errno
* value to indicate the nature of the error. See psock_setcockopt() for
* the list of possible error values.
*
****************************************************************************/
int can_setsockopt(FAR struct socket *psock, int option,
FAR const void *value, socklen_t value_len)
{
FAR struct can_conn_s *conn;
int ret;
int count = 0;
DEBUGASSERT(psock != NULL && value != NULL && psock->s_conn != NULL);
conn = (FAR struct can_conn_s *)psock->s_conn;
if (psock->s_type != SOCK_RAW)
{
nerr("ERROR: Not a RAW CAN socket\n");
return -ENOTCONN;
}
switch (option)
{
case CAN_RAW_FILTER:
if (value_len == 0)
{
conn->filter_count = 0;
ret = OK;
}
else if (value_len % sizeof(struct can_filter) != 0)
{
ret = -EINVAL;
}
else if (value_len > CONFIG_NET_CAN_RAW_FILTER_MAX *
sizeof(struct can_filter))
{
ret = -EINVAL;
}
else
{
count = value_len / sizeof(struct can_filter);
for (int i = 0; i < count; i++)
{
conn->filters[i] = ((struct can_filter *)value)[i];
}
conn->filter_count = count;
ret = OK;
}
break;
case CAN_RAW_ERR_FILTER:
break;
case CAN_RAW_LOOPBACK:
if (value_len != sizeof(conn->loopback))
{
return -EINVAL;
}
conn->loopback = *(FAR int32_t *)value;
break;
case CAN_RAW_RECV_OWN_MSGS:
if (value_len != sizeof(conn->recv_own_msgs))
{
return -EINVAL;
}
conn->recv_own_msgs = *(FAR int32_t *)value;
break;
case CAN_RAW_FD_FRAMES:
if (value_len != sizeof(conn->fd_frames))
{
return -EINVAL;
}
conn->fd_frames = *(FAR int32_t *)value;
break;
case CAN_RAW_JOIN_FILTERS:
break;
#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
case CAN_RAW_TX_DEADLINE:
if (value_len != sizeof(conn->tx_deadline))
{
return -EINVAL;
}
conn->tx_deadline = *(FAR int32_t *)value;
break;
#endif
default:
nerr("ERROR: Unrecognized CAN option: %d\n", option);
ret = -ENOPROTOOPT;
break;
}
return ret;
}
#endif /* CONFIG_NET_CANPROTO_OPTIONS */

856
net/can/can_sockif.c Normal file
View file

@ -0,0 +1,856 @@
/****************************************************************************
* net/can/can_sockif.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <string.h>
#include <poll.h>
#include <sched.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/semaphore.h>
#include <nuttx/wqueue.h>
#include <nuttx/net/net.h>
#include "can/can.h"
#include "netdev/netdev.h"
#ifdef CONFIG_NET_CAN
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int can_setup(FAR struct socket *psock, int protocol);
static sockcaps_t can_sockcaps(FAR struct socket *psock);
static void can_addref(FAR struct socket *psock);
static int can_bind(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen);
static int can_getsockname(FAR struct socket *psock,
FAR struct sockaddr *addr, FAR socklen_t *addrlen);
static int can_getpeername(FAR struct socket *psock,
FAR struct sockaddr *addr, FAR socklen_t *addrlen);
static int can_listen(FAR struct socket *psock, int backlog);
static int can_connect(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen);
static int can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR socklen_t *addrlen, FAR struct socket *newsock);
static int can_poll_local(FAR struct socket *psock, FAR struct pollfd *fds,
bool setup);
static ssize_t can_send(FAR struct socket *psock,
FAR const void *buf, size_t len, int flags);
static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags, FAR const struct sockaddr *to,
socklen_t tolen);
#ifdef CONFIG_NET_CMSG
static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
int flags);
#endif
static int can_close(FAR struct socket *psock);
/****************************************************************************
* Public Data
****************************************************************************/
const struct sock_intf_s g_can_sockif =
{
can_setup, /* si_setup */
can_sockcaps, /* si_sockcaps */
can_addref, /* si_addref */
can_bind, /* si_bind */
can_getsockname, /* si_getsockname */
can_getpeername, /* si_getpeername */
can_listen, /* si_listen */
can_connect, /* si_connect */
can_accept, /* si_accept */
can_poll_local, /* si_poll */
can_send, /* si_send */
can_sendto, /* si_sendto */
#ifdef CONFIG_NET_SENDFILE
NULL, /* si_sendfile */
#endif
can_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
can_recvmsg, /* si_recvmsg */
can_sendmsg, /* si_sendmsg */
#endif
can_close /* si_close */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: can_poll_eventhandler
*
* Description:
* This function is called to perform the actual CAN receive operation
* via the device interface layer. from can_input()
*
* Input Parameters:
* dev The structure of the network driver that caused the event
* conn The connection structure associated with the socket
* flags Set of events describing why the callback was invoked
*
* Returned Value:
* None
*
* Assumptions:
* This function must be called with the network locked.
*
****************************************************************************/
static uint16_t can_poll_eventhandler(FAR struct net_driver_s *dev,
FAR void *conn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct can_poll_s *info = (FAR struct can_poll_s *)pvpriv;
DEBUGASSERT(!info || (info->psock && info->fds));
/* 'priv' might be null in some race conditions (?) */
if (info)
{
pollevent_t eventset = 0;
/* Check for data or connection availability events. */
if ((flags & CAN_NEWDATA) != 0)
{
eventset |= (POLLIN & info->fds->events);
}
/* Check for loss of connection events. */
if ((flags & NETDEV_DOWN) != 0)
{
eventset |= (POLLHUP | POLLERR);
}
#if 0
/* A poll is a sign that we are free to send data. */
else if ((flags & CAN_POLL) != 0 &&
psock_udp_cansend(info->psock) >= 0)
{
eventset |= (POLLOUT & info->fds->events);
}
#endif
/* Awaken the caller of poll() is requested event occurred. */
if (eventset)
{
info->fds->revents |= eventset;
nxsem_post(info->fds->sem);
}
}
return flags;
}
/****************************************************************************
* Name: can_setup
*
* Description:
* Called for socket() to verify that the provided socket type and
* protocol are usable by this address family. Perform any family-
* specific socket fields.
*
* Input Parameters:
* psock - A pointer to a user allocated socket structure to be
* initialized.
* protocol - NetLink socket protocol (see sys/socket.h)
*
* Returned Value:
* Zero (OK) is returned on success. Otherwise, a negated errno value is
* returned.
*
****************************************************************************/
static int can_setup(FAR struct socket *psock, int protocol)
{
int domain = psock->s_domain;
int type = psock->s_type;
/* Verify that the protocol is supported */
DEBUGASSERT((unsigned int)protocol <= UINT8_MAX);
switch (protocol)
{
case 0: /* INET subsystem for netlib_ifup */
case CAN_RAW: /* RAW sockets */
case CAN_BCM: /* Broadcast Manager */
case CAN_TP16: /* VAG Transport Protocol v1.6 */
case CAN_TP20: /* VAG Transport Protocol v2.0 */
case CAN_MCNET: /* Bosch MCNet */
case CAN_ISOTP: /* ISO 15765-2 Transport Protocol */
case CAN_J1939: /* SAE J1939 */
break;
default:
return -EPROTONOSUPPORT;
}
/* Verify the socket type (domain should always be PF_CAN here) */
if (domain == PF_CAN && (type == SOCK_RAW || type == SOCK_DGRAM))
{
/* Allocate the NetLink socket connection structure and save it in the
* new socket instance.
*/
FAR struct can_conn_s *conn = can_alloc();
if (conn == NULL)
{
/* Failed to reserve a connection structure */
return -ENOMEM;
}
#ifdef CONFIG_NET_TIMESTAMP
/* Store psock in conn se we can read the SO_TIMESTAMP value */
conn->psock = psock;
#endif
/* Initialize the connection instance */
conn->protocol = (uint8_t)protocol;
/* Set the reference count on the connection structure. This
* reference count will be incremented only if the socket is
* dup'ed
*/
conn->crefs = 1;
/* Attach the connection instance to the socket */
psock->s_conn = conn;
return OK;
}
return -EPROTONOSUPPORT;
}
/****************************************************************************
* Name: can_sockcaps
*
* Description:
* Return the bit encoded capabilities of this socket.
*
* Input Parameters:
* psock - Socket structure of the socket whose capabilities are being
* queried.
*
* Returned Value:
* The non-negative set of socket capabilities is returned.
*
****************************************************************************/
static sockcaps_t can_sockcaps(FAR struct socket *psock)
{
/* Permit vfcntl to set socket to non-blocking */
return SOCKCAP_NONBLOCKING;
}
/****************************************************************************
* Name: can_addref
*
* Description:
* Increment the reference count on the underlying connection structure.
*
* Input Parameters:
* psock - Socket structure of the socket whose reference count will be
* incremented.
*
* Returned Value:
* None
*
****************************************************************************/
static void can_addref(FAR struct socket *psock)
{
FAR struct can_conn_s *conn;
DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
conn = psock->s_conn;
DEBUGASSERT(conn->crefs > 0 && conn->crefs < 255);
conn->crefs++;
}
/****************************************************************************
* Name: can_bind
*
* Description:
* can_bind() gives the socket 'conn' the local address 'addr'. 'addr'
* is 'addrlen' bytes long. Traditionally, this is called "assigning a name
* to a socket." When a socket is created with socket, it exists in a name
* space (address family) but has no name assigned.
*
* Input Parameters:
* conn NetLink socket connection structure
* addr Socket local address
* addrlen Length of 'addr'
*
* Returned Value:
* 0 on success; -1 on error with errno set appropriately
*
* EACCES
* The address is protected, and the user is not the superuser.
* EADDRINUSE
* The given address is already in use.
* EINVAL
* The socket is already bound to an address.
* ENOTSOCK
* psock is a descriptor for a file, not a socket.
*
* Assumptions:
*
****************************************************************************/
static int can_bind(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen)
{
FAR struct sockaddr_can *canaddr;
FAR struct can_conn_s *conn;
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
addrlen >= sizeof(struct sockaddr_can));
/* Save the address information in the connection structure */
canaddr = (FAR struct sockaddr_can *)addr;
conn = (FAR struct can_conn_s *)psock->s_conn;
/* Bind CAN device to socket */
#ifdef CONFIG_NETDEV_IFINDEX
conn->dev = netdev_findbyindex(canaddr->can_ifindex);
#else
char netdev_name[5] = "can0";
netdev_name[3] += canaddr->can_ifindex;
conn->dev = netdev_findbyname((const char *)&netdev_name);
#endif
return OK;
}
/****************************************************************************
* Name: can_getsockname
*
* Description:
* The getsockname() function retrieves the locally-bound name of the
* specified socket, stores this address in the sockaddr structure pointed
* to by the 'addr' argument, and stores the length of this address in the
* object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
*
* If the socket has not been bound to a local name, the value stored in
* the object pointed to by address is unspecified.
*
* Input Parameters:
* conn NetLink socket connection structure
* addr sockaddr structure to receive data [out]
* addrlen Length of sockaddr structure [in/out]
*
****************************************************************************/
static int can_getsockname(FAR struct socket *psock,
FAR struct sockaddr *addr,
FAR socklen_t *addrlen)
{
return -EAFNOSUPPORT;
}
/****************************************************************************
* Name: can_getpeername
*
* Description:
* The can_getpeername() function retrieves the remote-connected name
* of the specified packet socket, stores this address in the sockaddr
* structure pointed to by the 'addr' argument, and stores the length of
* this address in the object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
*
* If the socket has not been bound to a local name, the value stored in
* the object pointed to by address is unspecified.
*
* Parameters:
* psock Socket structure of the socket to be queried
* addr sockaddr structure to receive data [out]
* addrlen Length of sockaddr structure [in/out]
*
* Returned Value:
* On success, 0 is returned, the 'addr' argument points to the address
* of the socket, and the 'addrlen' argument points to the length of the
* address. Otherwise, a negated errno value is returned. See
* getpeername() for the list of appropriate error numbers.
*
****************************************************************************/
static int can_getpeername(FAR struct socket *psock,
FAR struct sockaddr *addr,
FAR socklen_t *addrlen)
{
return -EOPNOTSUPP;
}
/****************************************************************************
* Name: can_listen
*
* Description:
* To accept connections, a socket is first created with psock_socket(), a
* willingness to accept incoming connections and a queue limit for
* incoming connections are specified with psock_listen(), and then the
* connections are accepted with psock_accept(). For the case of AFINET
* and AFINET6 sockets, psock_listen() calls this function. The
* psock_listen() call applies only to sockets of type SOCK_STREAM or
* SOCK_SEQPACKET.
*
* Input Parameters:
* psock Reference to an internal, bound socket structure.
* backlog The maximum length the queue of pending connections may grow.
* If a connection request arrives with the queue full, the client
* may receive an error with an indication of ECONNREFUSED or,
* if the underlying protocol supports retransmission, the request
* may be ignored so that retries succeed.
*
* Returned Value:
* On success, zero is returned. On error, a negated errno value is
* returned. See list() for the set of appropriate error values.
*
****************************************************************************/
static int can_listen(FAR struct socket *psock, int backlog)
{
return -EOPNOTSUPP;
}
/****************************************************************************
* Name: can_connect
*
* Description:
* Perform a can connection
*
* Input Parameters:
* psock A reference to the socket structure of the socket
* to be connected
* addr The address of the remote server to connect to
* addrlen Length of address buffer
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static int can_connect(FAR struct socket *psock,
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
return -EOPNOTSUPP;
}
/****************************************************************************
* Name: can_accept
*
* Description:
* The can_accept function is used with connection-based socket
* types (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
* connection request on the queue of pending connections, creates a new
* connected socket with mostly the same properties as 'sockfd', and
* allocates a new socket descriptor for the socket, which is returned. The
* newly created socket is no longer in the listening state. The original
* socket 'sockfd' is unaffected by this call. Per file descriptor flags
* are not inherited across an inet_accept.
*
* The 'sockfd' argument is a socket descriptor that has been created with
* socket(), bound to a local address with bind(), and is listening for
* connections after a call to listen().
*
* On return, the 'addr' structure is filled in with the address of the
* connecting entity. The 'addrlen' argument initially contains the size
* of the structure pointed to by 'addr'; on return it will contain the
* actual length of the address returned.
*
* If no pending connections are present on the queue, and the socket is
* not marked as non-blocking, inet_accept blocks the caller until a
* connection is present. If the socket is marked non-blocking and no
* pending connections are present on the queue, inet_accept returns
* EAGAIN.
*
* Input Parameters:
* psock Reference to the listening socket structure
* addr Receives the address of the connecting client
* addrlen Input: Allocated size of 'addr'
* Return: Actual size returned size of 'addr'
* newsock Location to return the accepted socket information.
*
* Returned Value:
* Returns 0 (OK) on success. On failure, it returns a negated errno
* value. See accept() for a description of the appropriate error value.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static int can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR socklen_t *addrlen, FAR struct socket *newsock)
{
return -EOPNOTSUPP;
}
/****************************************************************************
* Name: can_poll_local
*
* Description:
* The standard poll() operation redirects operations on socket descriptors
* to this function.
*
* POLLUP: Will never be reported
* POLLERR: Reported in the event of any failure.
* POLLOUT: Always reported if requested.
* POLLIN: Reported if requested but only when pending response data is
* available
*
* Input Parameters:
* psock - An instance of the internal socket structure.
* fds - The structure describing the events to be monitored.
* setup - true: Setup up the poll; false: Tear down the poll
*
* Returned Value:
* 0: Success; Negated errno on failure
*
****************************************************************************/
static int can_poll_local(FAR struct socket *psock, FAR struct pollfd *fds,
bool setup)
{
FAR struct can_conn_s *conn;
FAR struct can_poll_s *info;
FAR struct devif_callback_s *cb;
int ret = OK;
DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
conn = (FAR struct can_conn_s *)psock->s_conn;
info = conn->pollinfo;
/* FIXME add NETDEV_DOWN support */
/* Check if we are setting up or tearing down the poll */
if (setup)
{
net_lock();
info->dev = conn->dev;
cb = can_callback_alloc(info->dev, conn);
if (cb == NULL)
{
ret = -EBUSY;
goto errout_with_lock;
}
/* Initialize the poll info container */
info->psock = psock;
info->fds = fds;
info->cb = cb;
/* Initialize the callback structure. Save the reference to the info
* structure as callback private data so that it will be available
* during callback processing.
*/
cb->flags = NETDEV_DOWN;
cb->priv = (FAR void *)info;
cb->event = can_poll_eventhandler;
if ((fds->events & POLLOUT) != 0)
{
cb->flags |= CAN_POLL;
}
if ((fds->events & POLLIN) != 0)
{
cb->flags |= CAN_NEWDATA;
}
/* Save the reference in the poll info structure as fds private as well
* for use during poll teardown as well.
*/
fds->priv = (FAR void *)info;
/* Check for read data availability now */
if (!IOB_QEMPTY(&conn->readahead))
{
/* Normal data may be read without blocking. */
fds->revents |= (POLLRDNORM & fds->events);
}
#if 0
if (psock_udp_cansend(psock) >= 0)
{
/* Normal data may be sent without blocking (at least one byte). */
fds->revents |= (POLLWRNORM & fds->events);
}
#endif
/* Check if any requested events are already in effect */
if (fds->revents != 0)
{
/* Yes.. then signal the poll logic */
nxsem_post(fds->sem);
}
errout_with_lock:
net_unlock();
}
else
{
info = (FAR struct can_poll_s *)fds->priv;
if (info != NULL)
{
/* Cancel any response notifications */
can_callback_free(info->dev, conn, info->cb);
/* Release the poll/select data slot */
info->fds->priv = NULL;
/* Then free the poll info container */
info->psock = NULL;
}
}
return ret;
}
/****************************************************************************
* Name: can_send
*
* Description:
* The can_send() call may be used only when the socket is in
* a connected state (so that the intended recipient is known).
*
* Input Parameters:
* psock - An instance of the internal socket structure.
* buf - Data to send
* len - Length of data to send
* flags - Send flags (ignored)
*
* Returned Value:
* On success, returns the number of characters sent. On error, a negated
* errno value is returned (see send() for the list of appropriate error
* values.
*
****************************************************************************/
static ssize_t can_send(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags)
{
ssize_t ret;
/* Only SOCK_RAW is supported */
if (psock->s_type == SOCK_RAW)
{
/* Raw packet send */
ret = psock_can_send(psock, buf, len);
}
else
{
/* EDESTADDRREQ. Signifies that the socket is not connection-mode and
* no peer address is set.
*/
ret = -EDESTADDRREQ;
}
return ret;
}
/****************************************************************************
* Name: can_sendto
*
* Description:
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
* socket, the parameters to and 'tolen' are ignored (and the error EISCONN
* may be returned when they are not NULL and 0), and the error ENOTCONN is
* returned when the socket was not actually connected.
*
* Input Parameters:
* psock A reference to the socket structure of the socket
* to be connected
* buf Data to send
* len Length of data to send
* flags Send flags (ignored)
* to Address of recipient
* tolen The length of the address structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags,
FAR const struct sockaddr *to, socklen_t tolen)
{
nerr("ERROR: sendto() not supported for raw packet sockets\n");
return -EAFNOSUPPORT;
}
/****************************************************************************
* Name: can_sendmsg
*
* Description:
* The can_sendmsg() send a CAN frame to psock
*
* Input Parameters:
* psock - An instance of the internal socket structure.
* msg - CAN frame and optional CMSG
* flags - Send flags (ignored)
*
* Returned Value:
* On success, returns the number of characters sent. On error, a negated
* errno value is returned (see send() for the list of appropriate error
* values.
*
****************************************************************************/
#ifdef CONFIG_NET_CMSG
static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
int flags)
{
ssize_t ret;
/* Only SOCK_RAW is supported */
if (psock->s_type == SOCK_RAW)
{
/* Raw packet send */
ret = psock_can_sendmsg(psock, msg);
}
else
{
/* EDESTADDRREQ. Signifies that the socket is not connection-mode and
* no peer address is set.
*/
ret = -EDESTADDRREQ;
}
return ret;
}
#endif
/****************************************************************************
* Name: can_close
*
* Description:
* Performs the close operation on a NetLink socket instance
*
* Input Parameters:
* psock Socket instance
*
* Returned Value:
* 0 on success; -1 on error with errno set appropriately.
*
* Assumptions:
*
****************************************************************************/
static int can_close(FAR struct socket *psock)
{
FAR struct can_conn_s *conn = psock->s_conn;
int ret = OK;
/* Perform some pre-close operations for the CAN socket type. */
/* Is this the last reference to the connection structure (there
* could be more if the socket was dup'ed).
*/
if (conn->crefs <= 1)
{
/* Yes... inform user-space daemon of socket close. */
#warning Missing logic
/* Free the connection structure */
conn->crefs = 0;
can_free(psock->s_conn);
if (ret < 0)
{
/* Return with error code, but free resources. */
nerr("ERROR: can_close failed: %d\n", ret);
return ret;
}
}
else
{
/* No.. Just decrement the reference count */
conn->crefs--;
}
return ret;
}
#endif /* CONFIG_NET_CAN */

View file

@ -66,6 +66,10 @@ ifeq ($(CONFIG_NET_PKT),y)
NET_CSRCS += devif_pktsend.c
endif
ifeq ($(CONFIG_NET_CAN),y)
NET_CSRCS += devif_cansend.c
endif
# Include network device interface build support
DEPPATH += --dep-path devif

View file

@ -68,31 +68,32 @@
*
* TCP_ACKDATA IN: Signifies that the outstanding data was ACKed and
* the socket layer should send out new data instead
* of retransmitting the last data (TCP only)
* of retransmitting the last data. (TCP only)
* OUT: Input state must be preserved on output.
*
* TCP_NEWDATA IN: Set to indicate that the peer has sent us new data.
* UDP_NEWDATA OUT: Cleared (only) by the socket layer logic to indicate
* ICMP_NEWDATA that the new data was consumed, suppressing further
* ICMPv6_NEWDATA attempts to process the new data.
* PKT_NEWDATA
* UDP_NEWDATA OUT: Cleared (only) by the socket layer logic to
* ICMP_NEWDATA indicate that the new data was consumed,
* ICMPv6_NEWDATA suppressing further attempts to process the new
* PKT_NEWDATA data.
* BLUETOOTH_NEWDATA
* IEEE802154_NEWDATA
*
* TCP_SNDACK IN: Not used; always zero
* OUT: Set by the socket layer if the new data was consumed
* and an ACK should be sent in the response. (TCP only)
* OUT: Set by the socket layer if the new data was
* consumed and an ACK should be sent in the response.
* (TCP only)
*
* TCP_REXMIT IN: Tells the socket layer to retransmit the data that
* was last sent. (TCP only)
* OUT: Not used
*
* TCP_POLL IN: Used for polling the socket layer. This is provided
* UDP_POLL periodically from the drivers to support (1) timed
* PKT_POLL operations, and (2) to check if the socket layer has
* BLUETOOTH_POLL data that it wants to send. These are socket oriented
* IEEE802154_POLL callbacks where the context depends on the specific
* set
* TCP_POLL IN: Used for polling the socket layer. This is
* UDP_POLL provided periodically from the drivers to support
* PKT_POLL (1) timed operations, and (2) to check if the
* BLUETOOTH_POLL socket layer has data that it wants to send.
* IEEE802154_POLL These are socket oriented callbacks where the
* context depends on the specific set.
* OUT: Not used
*
* TCP_BACKLOG IN: There is a new connection in the backlog list set
@ -104,14 +105,15 @@
* OUT: The socket layer signals that it wants to close the
* connection. (TCP only)
*
* TCP_ABORT IN: The remote host has aborted the connection, thus the
* connection has gone away. (TCP only)
* TCP_ABORT IN: The remote host has aborted the connection, thus
* the connection has gone away. (TCP only)
* OUT: The socket layer signals that it wants to abort the
* connection. (TCP only)
*
* TCP_CONNECTED IN: We have got a connection from a remote host and have
* set up a new connection for it, or an active connection
* has been successfully established. (TCP only)
* TCP_CONNECTED IN: We have got a connection from a remote host and
* have set up a new connection for it, or an active
* connection has been successfully established.
* (TCP only)
* OUT: Not used
*
* TCP_TIMEDOUT IN: The connection has been aborted due to too many
@ -121,37 +123,38 @@
* Device Specific Events: These are events that may be notified through
* callback lists residing in the network device structure.
*
* ARP_POLL IN: Used for polling the socket layer. This is provided
* periodically from the drivers to support (1) timed
* operations, and (2) to check if the ARP layer needs
* to send an ARP request. This is a device oriented
* event, not associated with a socket.
* ARP_POLL IN: Used for polling the socket layer. This is
* provided periodically from the drivers to support
* (1) timed operations, and (2) to check if the ARP
* layer needs to send an ARP request. This is a
* device oriented event, not associated with a
* socket.
* OUT: Not used
*
* ICMP_POLL IN: Used for polling the socket layer. This is provided
* periodically from the drivers to support (1) timed
* operations, and (2) to check if the ICMP layer needs
* to send an ARP request. This is a device oriented
* event, not associated with a socket. This differs
* from ICMPv6_POLL only in that the appdata pointer
* is set differently
* ICMP_POLL IN: Used for polling the socket layer. This is
* provided periodically from the drivers to support
* (1) timed operations, and (2) to check if the ICMP
* layer needs to send an ARP request. This is a
* device oriented event, not associated with a
* socket. This differs from ICMPv6_POLL only in that
* the appdata pointer is set differently.
* OUT: Not used
*
* ICMPv6_POLL IN: Used for polling the socket layer. This is provided
* periodically from the drivers to support (1) timed
* operations, and (2) to check if the ICMP layer needs
* to send an ARP request. This is a device oriented
* event, not associated with a socket. This differs
* from ICMP_POLL only in that the appdata pointer
* is set differently
* ICMPv6_POLL IN: Used for polling the socket layer. This is
* provided periodically from the drivers to support
* (1) timed operations, and (2) to check if the ICMP
* layer needs to send an ARP request. This is a
* device oriented event, not associated with a
* socket. This differs from ICMP_POLL only in that
* the appdata pointer is set differently.
* OUT: Not used
*
* IPFWD_POLL IN: Used for polling for forwarded packets layer. This
* is provided periodically from the drivers to support
* to check if there is a packet waiting to be forward
* on the device. This is a device oriented event,
* not associated with a socket. The appdata pointer
* The appdata pointer is not used in this case.
* is provided periodically from the drivers to
* support to check if there is a packet waiting to be
* forward on the device. This is a device oriented
* event, not associated with a socket. The appdata
* pointer is not used in this case.
* OUT: Not used
*
* NETDEV_DOWN: IN: The network device has been taken down.
@ -168,6 +171,7 @@
#define BLUETOOTH_NEWDATA TCP_NEWDATA
#define IEEE802154_NEWDATA TCP_NEWDATA
#define PKT_NEWDATA TCP_NEWDATA
#define CAN_NEWDATA TCP_NEWDATA
#define WPAN_NEWDATA TCP_NEWDATA
#define IPFWD_NEWDATA TCP_NEWDATA
#define TCP_SNDACK (1 << 2)
@ -175,6 +179,7 @@
#define TCP_POLL (1 << 4)
#define UDP_POLL TCP_POLL
#define PKT_POLL TCP_POLL
#define CAN_POLL TCP_POLL
#define BLUETOOTH_POLL TCP_POLL
#define IEEE802154_POLL TCP_POLL
#define WPAN_POLL TCP_POLL
@ -492,11 +497,32 @@ void devif_iob_send(FAR struct net_driver_s *dev, FAR struct iob_s *buf,
*
****************************************************************************/
#ifdef CONFIG_NET_PKT
#if defined(CONFIG_NET_PKT)
void devif_pkt_send(FAR struct net_driver_s *dev, FAR const void *buf,
unsigned int len);
#endif
/****************************************************************************
* Name: devif_can_send
*
* Description:
* Called from socket logic in order to send a raw packet in response to
* an xmit or poll request from the network interface driver.
*
* This is almost identical to calling devif_send() except that the data to
* be sent is copied into dev->d_buf (vs. dev->d_appdata), since there is
* no header on the data.
*
* Assumptions:
* This function must be called with the network locked.
*
****************************************************************************/
#if defined(CONFIG_NET_CAN)
void devif_can_send(FAR struct net_driver_s *dev, FAR const void *buf,
unsigned int len);
#endif
#undef EXTERN
#ifdef __cplusplus
}

113
net/devif/devif_cansend.c Normal file
View file

@ -0,0 +1,113 @@
/****************************************************************************
* net/devif/devif_cansend.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/net/netdev.h>
#if defined(CONFIG_NET_CAN)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Type Declarations
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Public Constant Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: devif_can_send
*
* Description:
* Called from socket logic in order to send a can packet in response to
* an xmit or poll request from the network interface driver.
*
* This is almost identical to calling devif_send() except that the data to
* be sent is copied into dev->d_buf (vs. dev->d_appdata), since there is
* no header on the data.
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
void devif_can_send(FAR struct net_driver_s *dev, FAR const void *buf,
unsigned int len)
{
DEBUGASSERT(dev && len > 0 && len < NETDEV_PKTSIZE(dev));
/* Copy the data into the device packet buffer */
memcpy(dev->d_buf, buf, len);
/* Set the number of bytes to send */
dev->d_len = len;
dev->d_sndlen = len;
}
#endif /* CONFIG_NET_CAN */

View file

@ -50,6 +50,7 @@
#include "devif/devif.h"
#include "arp/arp.h"
#include "can/can.h"
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
@ -232,6 +233,44 @@ static int devif_poll_pkt_connections(FAR struct net_driver_s *dev,
}
#endif /* CONFIG_NET_PKT */
/****************************************************************************
* Name: devif_poll_pkt_connections
*
* Description:
* Poll all packet connections for available packets to send.
*
* Assumptions:
* This function is called from the MAC device driver with the network
* locked.
*
****************************************************************************/
#ifdef CONFIG_NET_CAN
static int devif_poll_can_connections(FAR struct net_driver_s *dev,
devif_poll_callback_t callback)
{
FAR struct can_conn_s *can_conn = NULL;
int bstop = 0;
/* Traverse all of the allocated packet connections and
* perform the poll action
*/
while (!bstop && (can_conn = can_nextconn(can_conn)))
{
/* Perform the packet TX poll */
can_poll(dev, can_conn);
/* Call back into the driver */
bstop = callback(dev);
}
return bstop;
}
#endif /* CONFIG_NET_PKT */
/****************************************************************************
* Name: devif_poll_bluetooth_connections
*
@ -646,6 +685,15 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
if (!bstop)
#endif
#ifdef CONFIG_NET_CAN
{
/* Check for pending packet socket transfer */
bstop = devif_poll_can_connections(dev, callback);
}
if (!bstop)
#endif
#ifdef CONFIG_NET_BLUETOOTH
{
/* Check for pending PF_BLUETOOTH socket transfer */

View file

@ -102,6 +102,10 @@ const struct sock_intf_s g_icmp_sockif =
NULL, /* si_sendfile */
#endif
icmp_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
NULL, /* si_sendmsg */
#endif
icmp_close /* si_close */
};
@ -280,7 +284,8 @@ static int icmp_connect(FAR struct socket *psock,
* Input Parameters:
* psock Reference to the listening socket structure
* addr Receives the address of the connecting client
* addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
* addrlen Input: allocated size of 'addr',
* Return: returned size of 'addr'
* newsock Location to return the accepted socket information.
*
* Returned Value:
@ -318,7 +323,8 @@ static int icmp_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
*
****************************************************************************/
static int icmp_bind(FAR struct socket *psock, FAR const struct sockaddr *addr,
static int icmp_bind(FAR struct socket *psock,
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
/* An ICMP socket cannot be bound to a local address */
@ -364,10 +370,10 @@ static int icmp_getsockname(FAR struct socket *psock,
* Name: icmp_getpeername
*
* Description:
* The icmp_getpeername() function retrieves the remote-connected name of the
* specified packet socket, stores this address in the sockaddr structure
* pointed to by the 'addr' argument, and stores the length of this
* address in the object pointed to by the 'addrlen' argument.
* The icmp_getpeername() function retrieves the remote-connected name of
* the specified packet socket, stores this address in the sockaddr
* structure pointed to by the 'addr' argument, and stores the length of
* this address in the object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.

View file

@ -102,6 +102,10 @@ const struct sock_intf_s g_icmpv6_sockif =
NULL, /* si_sendfile */
#endif
icmpv6_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
NULL, /* si_sendmsg */
#endif
icmpv6_close /* si_close */
};
@ -280,7 +284,8 @@ static int icmpv6_connect(FAR struct socket *psock,
* Input Parameters:
* psock Reference to the listening socket structure
* addr Receives the address of the connecting client
* addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
* addrlen Input: allocated size of 'addr',
* Return: returned size of 'addr'
* newsock Location to return the accepted socket information.
*
* Returned Value:
@ -318,8 +323,9 @@ static int icmpv6_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
*
****************************************************************************/
static int icmpv6_bind(FAR struct socket *psock, FAR const struct sockaddr *addr,
socklen_t addrlen)
static int icmpv6_bind(FAR struct socket *psock,
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
/* An ICMPv6 socket cannot be bound to a local address */
@ -330,10 +336,10 @@ static int icmpv6_bind(FAR struct socket *psock, FAR const struct sockaddr *addr
* Name: icmpv6_getsockname
*
* Description:
* The icmpv6_getsockname() function retrieves the locally-bound name of the
* specified packet socket, stores this address in the sockaddr structure
* pointed to by the 'addr' argument, and stores the length of this
* address in the object pointed to by the 'addrlen' argument.
* The icmpv6_getsockname() function retrieves the locally-bound name of
* the specified packet socket, stores this address in the sockaddr
* structure pointed to by the 'addr' argument, and stores the length of
* this address in the object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
@ -364,10 +370,10 @@ static int icmpv6_getsockname(FAR struct socket *psock,
* Name: icmpv6_getpeername
*
* Description:
* The icmpv6_getpeername() function retrieves the remote-connected name of the
* specified packet socket, stores this address in the sockaddr structure
* pointed to by the 'addr' argument, and stores the length of this
* address in the object pointed to by the 'addrlen' argument.
* The icmpv6_getpeername() function retrieves the remote-connected name of
* the specified packet socket, stores this address in the sockaddr
* structure pointed to by the 'addr' argument, and stores the length of
* this address in the object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
@ -483,8 +489,8 @@ static int icmpv6_netpoll(FAR struct socket *psock, FAR struct pollfd *fds,
static ssize_t icmpv6_send(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags)
{
/* ICMPv6 sockets cannot be bound and, hence, cannot support any connection-
* oriented data transfer.
/* ICMPv6 sockets cannot be bound and, hence, cannot support any
* connection-oriented data transfer.
*/
return -EDESTADDRREQ;

View file

@ -107,6 +107,10 @@ const struct sock_intf_s g_ieee802154_sockif =
NULL, /* si_sendfile */
#endif
ieee802154_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
NULL, /* si_sendmsg */
#endif
ieee802154_close /* si_close */
};
@ -241,10 +245,10 @@ static void ieee802154_addref(FAR struct socket *psock)
* Name: ieee802154_connect
*
* Description:
* ieee802154_connect() connects the local socket referred to by the structure
* 'psock' to the address specified by 'addr'. The addrlen argument
* specifies the size of 'addr'. The format of the address in 'addr' is
* determined by the address space of the socket 'psock'.
* ieee802154_connect() connects the local socket referred to by the
* structure 'psock' to the address specified by 'addr'. The addrlen
* argument specifies the size of 'addr'. The format of the address in
* 'addr' is determined by the address space of the socket 'psock'.
*
* If the socket 'psock' is of type SOCK_DGRAM then 'addr' is the address
* to which datagrams are sent by default, and the only address from which
@ -307,8 +311,8 @@ static int ieee802154_connect(FAR struct socket *psock,
* Name: ieee802154_accept
*
* Description:
* The ieee802154_accept function is used with connection-based socket types
* (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
* The ieee802154_accept function is used with connection-based socket
* types (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
* connection request on the queue of pending connections, creates a new
* connected socket with mostly the same properties as 'sockfd', and
* allocates a new socket descriptor for the socket, which is returned. The
@ -334,7 +338,8 @@ static int ieee802154_connect(FAR struct socket *psock,
* Input Parameters:
* psock Reference to the listening socket structure
* addr Receives the address of the connecting client
* addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
* addrlen Input: allocated size of 'addr',
* Return: returned size of 'addr'
* newsock Location to return the accepted socket information.
*
* Returned Value:
@ -376,7 +381,8 @@ static int ieee802154_accept(FAR struct socket *psock,
****************************************************************************/
static int ieee802154_bind(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen)
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
FAR const struct sockaddr_ieee802154_s *iaddr;
FAR struct radio_driver_s *radio;
@ -446,10 +452,10 @@ static int ieee802154_bind(FAR struct socket *psock,
* Name: ieee802154_getsockname
*
* Description:
* The ieee802154_getsockname() function retrieves the locally-bound name of the
* specified packet socket, stores this address in the sockaddr structure
* pointed to by the 'addr' argument, and stores the length of this
* address in the object pointed to by the 'addrlen' argument.
* The ieee802154_getsockname() function retrieves the locally-bound name
* of the specified packet socket, stores this address in the sockaddr
* structure pointed to by the 'addr' argument, and stores the length of
* this address in the object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
@ -508,10 +514,10 @@ static int ieee802154_getsockname(FAR struct socket *psock,
* Name: ieee802154_getpeername
*
* Description:
* The ieee802154_getpeername() function retrieves the remote-connectd name of the
* specified packet socket, stores this address in the sockaddr structure
* pointed to by the 'addr' argument, and stores the length of this
* address in the object pointed to by the 'addrlen' argument.
* The ieee802154_getpeername() function retrieves the remote-connectd name
* of the specified packet socket, stores this address in the sockaddr
* structure pointed to by the 'addr' argument, and stores the length of
* this address in the object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
@ -676,7 +682,8 @@ static ssize_t ieee802154_send(FAR struct socket *psock, FAR const void *buf,
ret = psock_ieee802154_sendto(psock, buf, len, flags,
(FAR const struct sockaddr *)&to,
sizeof(struct sockaddr_ieee802154_s));
sizeof(
struct sockaddr_ieee802154_s));
}
}
else
@ -713,9 +720,11 @@ static ssize_t ieee802154_send(FAR struct socket *psock, FAR const void *buf,
*
****************************************************************************/
static ssize_t ieee802154_sendto(FAR struct socket *psock, FAR const void *buf,
static ssize_t ieee802154_sendto(FAR struct socket *psock,
FAR const void *buf,
size_t len, int flags,
FAR const struct sockaddr *to, socklen_t tolen)
FAR const struct sockaddr *to,
socklen_t tolen)
{
ssize_t ret;

View file

@ -117,6 +117,10 @@ static const struct sock_intf_s g_inet_sockif =
inet_sendfile, /* si_sendfile */
#endif
inet_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
NULL, /* si_sendmsg */
#endif
inet_close /* si_close */
};

View file

@ -47,6 +47,7 @@
#include <debug.h>
#include <nuttx/fs/fs.h>
#include "devif/devif.h"
#include "local/local.h"

View file

@ -110,6 +110,10 @@ const struct sock_intf_s g_local_sockif =
NULL, /* si_sendfile */
#endif
local_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
NULL, /* si_sendmsg */
#endif
local_close /* si_close */
};
@ -161,7 +165,8 @@ static int local_sockif_alloc(FAR struct socket *psock)
* specific socket fields.
*
* Input Parameters:
* psock A pointer to a user allocated socket structure to be initialized.
* psock A pointer to a user allocated socket structure
* to be initialized.
* protocol (see sys/socket.h)
*
* Returned Value:
@ -590,7 +595,8 @@ static int local_connect(FAR struct socket *psock,
* Input Parameters:
* psock Reference to the listening socket structure
* addr Receives the address of the connecting client
* addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
* addrlen Input: allocated size of 'addr',
* Return: returned size of 'addr'
* newsock Location to return the accepted socket information.
*
* Returned Value:
@ -717,7 +723,7 @@ static ssize_t local_send(FAR struct socket *psock, FAR const void *buf,
* Name: local_sendto
*
* Description:
* Implements the sendto() operation for the case of the local, Unix socket.
* Implements the sendto() operation for the case of the local Unix socket.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure

View file

@ -59,6 +59,7 @@
#include "bluetooth/bluetooth.h"
#include "ieee802154/ieee802154.h"
#include "local/local.h"
#include "can/can.h"
#include "netlink/netlink.h"
#include "igmp/igmp.h"
#include "route/route.h"
@ -158,6 +159,12 @@ void net_initialize(void)
local_initialize();
#endif
#ifdef CONFIG_NET_CAN
/* Initialize SocketCAN support */
can_initialize();
#endif
#ifdef CONFIG_NET_NETLINK
/* Initialize the Netlink IPC support */

View file

@ -16,6 +16,14 @@ config NETDEV_PHY_IOCTL
---help---
Enable support for ioctl() commands to access PHY registers
config NETDEV_CAN_BITRATE_IOCTL
bool "Enable CAN bitrate ioctl()"
default n
select NETDEV_IOCTL
depends on NET_CAN
---help---
Enable support for ioctl() commands to change CAN bitrate
config NETDEV_WIRELESS_IOCTL
bool "Enable Wireless ioctl()"
default n

View file

@ -1088,6 +1088,54 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd,
}
}
break;
#endif
#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL)
case SIOCGCANBITRATE: /* Get bitrate from a CAN controller */
case SIOCSCANBITRATE: /* Set bitrate of a CAN controller */
{
dev = netdev_ifr_dev(req);
if (dev && dev->d_ioctl)
{
struct can_ioctl_data_s *can_bitrate_data =
&req->ifr_ifru.ifru_can_data;
ret = dev->d_ioctl(dev, cmd,
(unsigned long)(uintptr_t)can_bitrate_data);
}
}
break;
#endif
#ifdef CONFIG_NETDEV_IFINDEX
case SIOCGIFNAME: /* Get interface name */
{
struct net_driver_s *dev = netdev_findbyindex(req->ifr_ifindex);
if (dev != NULL)
{
strncpy(req->ifr_name, dev->d_ifname, IFNAMSIZ);
ret = OK;
}
else
{
ret = -ENODEV;
}
}
break;
case SIOCGIFINDEX: /* Index to name mapping */
{
struct net_driver_s *dev = netdev_findbyname(req->ifr_name);
if (dev != NULL)
{
req->ifr_ifindex = dev->d_ifindex;
ret = OK;
}
else
{
ret = -ENODEV;
}
}
break;
#endif
default:

View file

@ -37,6 +37,7 @@
#include <nuttx/net/netdev.h>
#include <nuttx/net/ethernet.h>
#include <nuttx/net/bluetooth.h>
#include <nuttx/net/can.h>
#include "utils/utils.h"
#include "igmp/igmp.h"
@ -56,6 +57,7 @@
#define NETDEV_WLAN_FORMAT "wlan%d"
#define NETDEV_WPAN_FORMAT "wpan%d"
#define NETDEV_WWAN_FORMAT "wwan%d"
#define NETDEV_CAN_FORMAT "can%d"
#if defined(CONFIG_DRIVERS_IEEE80211) /* Usually also has CONFIG_NET_ETHERNET */
# define NETDEV_DEFAULT_FORMAT NETDEV_WLAN_FORMAT
@ -67,6 +69,8 @@
# define NETDEV_DEFAULT_FORMAT NETDEV_SLIP_FORMAT
#elif defined(CONFIG_NET_TUN)
# define NETDEV_DEFAULT_FORMAT NETDEV_TUN_FORMAT
#elif defined(CONFIG_NET_CAN)
# define NETDEV_DEFAULT_FORMAT NETDEV_CAN_FORMAT
#else /* if defined(CONFIG_NET_LOOPBACK) */
# define NETDEV_DEFAULT_FORMAT NETDEV_LO_FORMAT
#endif
@ -277,6 +281,14 @@ int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype)
break;
#endif
#ifdef CONFIG_NET_CAN
case NET_LL_CAN: /* CAN bus */
dev->d_llhdrlen = 0;
dev->d_pktsize = NET_CAN_PKTSIZE;
devfmt = NETDEV_CAN_FORMAT;
break;
#endif
#ifdef CONFIG_NET_BLUETOOTH
case NET_LL_BLUETOOTH: /* Bluetooth */
llhdrlen = BLUETOOTH_MAX_HDRLEN; /* Determined at runtime */

View file

@ -111,6 +111,10 @@ const struct sock_intf_s g_netlink_sockif =
NULL, /* si_sendfile */
#endif
netlink_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
NULL, /* si_sendmsg */
#endif
netlink_close /* si_close */
};

View file

@ -108,6 +108,10 @@ const struct sock_intf_s g_pkt_sockif =
NULL, /* si_sendfile */
#endif
pkt_recvfrom, /* si_recvfrom */
#ifdef CONFIG_NET_CMSG
NULL, /* si_recvmsg */
NULL, /* si_sendmsg */
#endif
pkt_close /* si_close */
};

View file

@ -37,6 +37,12 @@ config NET_UDPPROTO_OPTIONS
---help---
Enable or disable support for UDP protocol level socket options.
config NET_CANPROTO_OPTIONS
bool
default n
---help---
Enable or disable support for CAN protocol level socket option
if NET_SOCKOPTS
config NET_SOLINGER
@ -49,5 +55,23 @@ config NET_SOLINGER
Enable or disable support for the SO_LINGER socket option. Requires
write buffer support.
config NET_TIMESTAMP
bool "SO_TIMESTAMP socket option"
default n
depends on NET_CAN
select NET_CMSG
---help---
Enable or disable support for the SO_TIMESTAMP socket option. Currently only tested & implemented in SocketCAN but should work on all sockets
endif # NET_SOCKOPTS
config NET_CMSG
bool "Control messages (CMSG) support"
default n
---help---
Enable or disable support for control messages in the recvmsg() and
sendmsg() function. Control messages (also defined in POSIX 1003.1g
as ancillary data object information). Includes additional
information on the packet received or to be transmitted.
endmenu # Socket Support

View file

@ -74,3 +74,9 @@ endif
DEPPATH += --dep-path socket
VPATH += :socket
# Support for control messages (CMSG)
ifeq ($(CONFIG_NET_CMSG),y)
SOCK_CSRCS += recvmsg.c
SOCK_CSRCS += sendmsg.c
endif

View file

@ -278,6 +278,19 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
}
break;
#ifdef CONFIG_NET_TIMESTAMP
case SO_TIMESTAMP:
{
if (*value_len != sizeof(int))
{
return -EINVAL;
}
*(FAR int *)value = (int)psock->s_timestamp;
}
break;
#endif
/* The following are not yet implemented
* (return values other than {0,1})
*/
@ -371,6 +384,12 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
break;
#endif
case SOL_CAN_RAW:/* CAN protocol socket options (see include/netpacket/can.h) */
#ifdef CONFIG_NET_CANPROTO_OPTIONS
ret = can_getsockopt(psock, option, value, value_len);
#endif
break;
/* These levels are defined in sys/socket.h, but are not yet
* implemented.
*/

View file

@ -47,6 +47,7 @@
#include "inet/inet.h"
#include "local/local.h"
#include "can/can.h"
#include "netlink/netlink.h"
#include "pkt/pkt.h"
#include "bluetooth/bluetooth.h"
@ -104,6 +105,12 @@ net_sockif(sa_family_t family, int type, int protocol)
break;
#endif
#ifdef CONFIG_NET_CAN
case PF_CAN:
sockif = &g_can_sockif;
break;
#endif
#ifdef CONFIG_NET_NETLINK
case PF_NETLINK:
sockif = &g_netlink_sockif;

244
net/socket/recvmsg.c Normal file
View file

@ -0,0 +1,244 @@
/****************************************************************************
* net/socket/recvmsg.c
*
* Copyright (C) 2007-2009, 2011-2017, 2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/cancelpt.h>
#include <nuttx/net/net.h>
#include "socket/socket.h"
#ifdef CONFIG_NET_CMSG
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: psock_recvmsg
*
* Description:
* psock_recvfrom() receives messages from a socket, and may be used to
* receive data on a socket whether or not it is connection-oriented.
* This is an internal OS interface. It is functionally equivalent to
* recvfrom() except that:
*
* - It is not a cancellation point,
* - It does not modify the errno variable, and
* - I accepts the internal socket structure as an input rather than an
* task-specific socket descriptor.
*
* Input Parameters:
* psock - A pointer to a NuttX-specific, internal socket structure
* msg Buffer to receive msg
* len - Length of buffer
* flags - Receive flags
*
* Returned Value:
* On success, returns the number of characters sent. If no data is
* available to be received and the peer has performed an orderly shutdown,
* recv() will return 0. Otherwise, on any failure, a negated errno value
* is returned (see comments with send() for a list of appropriate errno
* values).
*
****************************************************************************/
ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
int flags)
{
/* Verify that non-NULL pointers were passed */
if (msg == NULL)
{
return -EINVAL;
}
if (msg->msg_iovlen != 1)
{
return -ENOTSUP;
}
/* Verify that the sockfd corresponds to valid, allocated socket */
if (psock == NULL || psock->s_crefs <= 0)
{
return -EBADF;
}
/* Let logic specific to this address family handle the recvfrom()
* operation.
*/
DEBUGASSERT(psock->s_sockif != NULL &&
(psock->s_sockif->si_recvmsg != NULL ||
psock->s_sockif->si_recvfrom != NULL));
if (psock->s_sockif->si_recvmsg != NULL)
{
return psock->s_sockif->si_recvmsg(psock, msg, flags);
}
else
{
/* Socket doesn't implement si_recvmsg fallback to si_recvfrom */
FAR void *buf = msg->msg_iov->iov_base;
FAR struct sockaddr *from = msg->msg_name;
FAR socklen_t *fromlen = (FAR socklen_t *)&msg->msg_namelen;
size_t len = msg->msg_iov->iov_len;
return psock->s_sockif->si_recvfrom(psock, buf, len, flags, from,
fromlen);
}
}
/****************************************************************************
* Name: nx_recvfrom
*
* Description:
* nx_recvfrom() receives messages from a socket, and may be used to
* receive data on a socket whether or not it is connection-oriented.
* This is an internal OS interface. It is functionally equivalent to
* recvfrom() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno variable.
*
* Input Parameters:
* sockfd - Socket descriptor of socket
* msg Buffer to receive msg
* len - Length of buffer
* flags - Receive flags
*
* Returned Value:
* On success, returns the number of characters sent. If no data is
* available to be received and the peer has performed an orderly shutdown,
* recv() will return 0. Otherwise, on any failure, a negated errno value
* is returned (see comments with send() for a list of appropriate errno
* values).
*
****************************************************************************/
ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
{
FAR struct socket *psock;
/* Get the underlying socket structure */
psock = sockfd_socket(sockfd);
/* Then let psock_recvmsg() do all of the work */
return psock_recvmsg(psock, msg, flags);
}
/****************************************************************************
* Function: recvmsg
*
* Description:
* The recvmsg() call is identical to recvfrom() with a NULL from
* parameter.
*
* Parameters:
* sockfd Socket descriptor of socket
* msg Buffer to receive msg
* len Length of buffer
* flags Receive flags
*
* Returned Value:
* On success, returns the number of characters received. On error,
* -1 is returned, and errno is set appropriately:
*
* EAGAIN
* The socket is marked non-blocking and the receive operation would
* block, or a receive timeout had been set and the timeout expired
* before data was received.
* EBADF
* The argument sockfd is an invalid descriptor.
* ECONNREFUSED
* A remote host refused to allow the network connection (typically
* because it is not running the requested service).
* EFAULT
* The receive buffer pointer(s) point outside the process's address
* space.
* EINTR
* The receive was interrupted by delivery of a signal before any data
* were available.
* EINVAL
* Invalid argument passed.
* ENOMEM
* Could not allocate memory.
* ENOTCONN
* The socket is associated with a connection-oriented protocol and has
* not been connected.
* ENOTSOCK
* The argument sockfd does not refer to a socket.
*
****************************************************************************/
ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
{
FAR struct socket *psock;
ssize_t ret;
/* recvfrom() is a cancellation point */
enter_cancellation_point();
/* Get the underlying socket structure */
psock = sockfd_socket(sockfd);
/* Let psock_recvfrom() do all of the work */
ret = psock_recvmsg(psock, msg, flags);
if (ret < 0)
{
_SO_SETERRNO(psock, -ret);
ret = ERROR;
}
leave_cancellation_point();
return ret;
}
#endif /* CONFIG_NET_CMSG */

243
net/socket/sendmsg.c Normal file
View file

@ -0,0 +1,243 @@
/****************************************************************************
* net/socket/sendmsg.c
*
* Copyright (C) 2007-2009, 2011-2017, 2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/cancelpt.h>
#include <nuttx/net/net.h>
#include "socket/socket.h"
#ifdef CONFIG_NET_CMSG
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: psock_sendmsg
*
* Description:
* psock_sendfrom() sends messages to a socket, and may be used to
* send data on a socket whether or not it is connection-oriented.
* This is an internal OS interface. It is functionally equivalent to
* sendfrom() except that:
*
* - It is not a cancellation point,
* - It does not modify the errno variable, and
* - I accepts the internal socket structure as an input rather than an
* task-specific socket descriptor.
*
* Input Parameters:
* psock - A pointer to a NuttX-specific, internal socket structure
* msg - Buffer to of the msg
* len - Length of buffer
* flags - Receive flags
*
* Returned Value:
* On success, returns the number of characters sent. If no data is
* available to be received and the peer has performed an orderly shutdown,
* send() will return 0. Otherwise, on any failure, a negated errno value
* is returned (see comments with send() for a list of appropriate errno
* values).
*
****************************************************************************/
ssize_t psock_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
int flags)
{
/* Verify that non-NULL pointers were passed */
if (msg == NULL)
{
return -EINVAL;
}
if (msg->msg_iovlen != 1)
{
return -ENOTSUP;
}
/* Verify that the sockfd corresponds to valid, allocated socket */
if (psock == NULL || psock->s_crefs <= 0)
{
return -EBADF;
}
/* Let logic specific to this address family handle the sendfrom()
* operation.
*/
DEBUGASSERT(psock->s_sockif != NULL &&
(psock->s_sockif->si_sendmsg != NULL ||
psock->s_sockif->si_sendto != NULL));
if (psock->s_sockif->si_sendmsg != NULL)
{
return psock->s_sockif->si_sendmsg(psock, msg, flags);
}
else
{
/* Socket doesn't implement si_sendmsg fallback to si_sendto */
FAR void *buf = msg->msg_iov->iov_base;
FAR struct sockaddr *to = msg->msg_name;
socklen_t tolen = msg->msg_namelen;
size_t len = msg->msg_iov->iov_len;
return psock->s_sockif->si_sendto(psock, buf, len, flags, to, tolen);
}
}
/****************************************************************************
* Name: nx_sendfrom
*
* Description:
* nx_sendfrom() receives messages from a socket, and may be used to
* receive data on a socket whether or not it is connection-oriented.
* This is an internal OS interface. It is functionally equivalent to
* sendfrom() except that:
*
* - It is not a cancellation point, and
* - It does not modify the errno variable.
*
* Input Parameters:
* sockfd - Socket descriptor of socket
* msg Buffer to receive msg
* len - Length of buffer
* flags - Receive flags
*
* Returned Value:
* On success, returns the number of characters sent. If no data is
* available to be received and the peer has performed an orderly shutdown,
* send() will return 0. Otherwise, on any failure, a negated errno value
* is returned (see comments with send() for a list of appropriate errno
* values).
*
****************************************************************************/
ssize_t nx_sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
{
FAR struct socket *psock;
/* Get the underlying socket structure */
psock = sockfd_socket(sockfd);
/* Then let psock_sendmsg() do all of the work */
return psock_sendmsg(psock, msg, flags);
}
/****************************************************************************
* Function: sendmsg
*
* Description:
* The sendmsg() call is identical to sendfrom() with a NULL from
* parameter.
*
* Parameters:
* sockfd Socket descriptor of socket
* msg Buffer to receive msg
* len Length of buffer
* flags Receive flags
*
* Returned Value:
* On success, returns the number of characters received. On error,
* -1 is returned, and errno is set appropriately:
*
* EAGAIN
* The socket is marked non-blocking and the receive operation would
* block, or a receive timeout had been set and the timeout expired
* before data was received.
* EBADF
* The argument sockfd is an invalid descriptor.
* ECONNREFUSED
* A remote host refused to allow the network connection (typically
* because it is not running the requested service).
* EFAULT
* The receive buffer pointer(s) point outside the process's address
* space.
* EINTR
* The receive was interrupted by delivery of a signal before any data
* were available.
* EINVAL
* Invalid argument passed.
* ENOMEM
* Could not allocate memory.
* ENOTCONN
* The socket is associated with a connection-oriented protocol and has
* not been connected.
* ENOTSOCK
* The argument sockfd does not refer to a socket.
*
****************************************************************************/
ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
{
FAR struct socket *psock;
ssize_t ret;
/* sendfrom() is a cancellation point */
enter_cancellation_point();
/* Get the underlying socket structure */
psock = sockfd_socket(sockfd);
/* Let psock_sendfrom() do all of the work */
ret = psock_sendmsg(psock, msg, flags);
if (ret < 0)
{
_SO_SETERRNO(psock, -ret);
ret = ERROR;
}
leave_cancellation_point();
return ret;
}
#endif /* CONFIG_NET_CMSG */

View file

@ -279,6 +279,29 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
}
break;
#endif
#ifdef CONFIG_NET_TIMESTAMP
case SO_TIMESTAMP: /* Generates a timestamp for each incoming packet */
{
/* Verify that option is at least the size of an integer. */
if (value_len < sizeof(FAR int32_t))
{
return -EINVAL;
}
/* Lock the network so that we have exclusive access to the socket
* options.
*/
net_lock();
psock->s_timestamp = *((FAR int32_t *)value);
net_unlock();
}
break;
#endif
/* The following are not yet implemented */
case SO_RCVBUF: /* Sets receive buffer size */
@ -399,6 +422,12 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
break;
#endif
#ifdef CONFIG_NET_CANPROTO_OPTIONS
case SOL_CAN_RAW: /* CAN protocol socket options (see include/netpacket/can.h) */
ret = can_setsockopt(psock, option, value, value_len);
break;
#endif
default: /* The provided level is invalid */
ret = -EINVAL;
break;

View file

@ -80,7 +80,7 @@
/* This is the largest option value. REVISIT: belongs in sys/socket.h */
#define _SO_MAXOPT (15)
#define _SO_MAXOPT (16)
/* Macros to set, test, clear options */

View file

@ -228,6 +228,57 @@ int net_lock(void)
return ret;
}
/****************************************************************************
* Name: net_trylock
*
* Description:
* Try to take the network lock only when it is currently not locked.
* Otherwise, it locks the semaphore. In either
* case, the call returns without blocking.
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* failured (probably -EAGAIN).
*
****************************************************************************/
int net_trylock(void)
{
#ifdef CONFIG_SMP
irqstate_t flags = enter_critical_section();
#endif
pid_t me = getpid();
int ret = OK;
/* Does this thread already hold the semaphore? */
if (g_holder == me)
{
/* Yes.. just increment the reference count */
g_count++;
}
else
{
ret = nxsem_trywait(&g_netlock);
if (ret >= 0)
{
/* Now this thread holds the semaphore */
g_holder = me;
g_count = 1;
}
}
#ifdef CONFIG_SMP
leave_critical_section(flags);
#endif
return ret;
}
/****************************************************************************
* Name: net_unlock
*