net: Add SocketCAN support
This commit is contained in:
parent
a607e6257f
commit
55d9e5f7af
54 changed files with 5741 additions and 114 deletions
|
@ -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
|
||||
|
|
|
@ -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
140
include/netpacket/can.h
Normal 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
319
include/nuttx/can.h
Normal 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
129
include/nuttx/can/error.h
Normal 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 */
|
|
@ -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
122
include/nuttx/net/can.h
Normal 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 */
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
97
net/can/Kconfig
Normal 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
48
net/can/Make.defs
Normal 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
385
net/can/can.h
Normal 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
242
net/can/can_callback.c
Normal 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
223
net/can/can_conn.c
Normal 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
220
net/can/can_getsockopt.c
Normal 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
204
net/can/can_input.c
Normal 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
83
net/can/can_notifier.c
Normal 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
88
net/can/can_poll.c
Normal 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
838
net/can/can_recvfrom.c
Normal 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
441
net/can/can_send.c
Normal 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
177
net/can/can_setsockopt.c
Normal 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
856
net/can/can_sockif.c
Normal 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 */
|
|
@ -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
|
||||
|
|
|
@ -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
113
net/devif/devif_cansend.c
Normal 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 */
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include "devif/devif.h"
|
||||
|
||||
#include "local/local.h"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
244
net/socket/recvmsg.c
Normal 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
243
net/socket/sendmsg.c
Normal 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 */
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue