!934 Add CANBUS framework support on liteos

Merge pull request !934 from NickYang/master
This commit is contained in:
openharmony_ci
2022-04-29 13:49:43 +00:00
committed by Gitee
14 changed files with 1298 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef CAN_IF_H
#define CAN_IF_H
#include "platform_if.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define CAN_DATA_LEN 8
enum CanBusState {
CAN_BUS_RESET,
CAN_BUS_READY,
CAN_BUS_BUSY,
CAN_BUS_STOP,
CAN_BUS_SLEEP,
CAN_BUS_ERROR,
CAN_BUS_INVALID,
};
enum CanBusMode {
CAN_BUS_NORMAL,
CAN_BUS_LOOPBACK,
};
struct CanMsg {
union {
uint32_t id11 : 11;
uint32_t id29 : 29;
uint32_t id : 29;
};
uint32_t ide : 1;
uint32_t rtr : 1;
uint32_t padding : 1;
uint8_t dlc;
uint8_t data[CAN_DATA_LEN];
int32_t error;
const struct CanFilter *filter;
};
enum CanEvent {
CAN_EVENT_MSG_RECEIVED,
CAN_EVENT_MSG_SENT,
CAN_EVENT_ERROR,
};
enum CanFilterType {
CAN_FILTER_HW = 1,
};
struct CanFilter {
uint32_t rtr : 1;
uint32_t ide : 1;
uint32_t id : 29;
uint32_t rtrMask : 1;
uint32_t ideMask : 1;
uint32_t idMask : 29;
uint32_t type : 2;
};
struct CanConfig {
uint32_t speed;
uint8_t mode;
};
int32_t CanBusOpen(int32_t number, DevHandle *handle);
void CanBusClose(DevHandle handle);
int32_t CanBusSendMsg(DevHandle handle, const struct CanMsg *msg);
int32_t CanBusReadMsg(DevHandle handle, struct CanMsg *msg, uint32_t tms);
int32_t CanBusAddFilter(DevHandle handle, const struct CanFilter *filter);
int32_t CanBusDelFilter(DevHandle handle, const struct CanFilter *filter);
int32_t CanBusSetCfg(DevHandle handle, const struct CanConfig *cfg);
int32_t CanBusGetCfg(DevHandle handle, struct CanConfig *cfg);
int32_t CanBusGetState(DevHandle handle);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CAN_IF_H */
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef CAN_CLIENT_H
#define CAN_CLIENT_H
#include "can_core.h"
#include "can_mail.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct CanClient;
int32_t CanClientCreateByNumber(int32_t busNum, struct CanClient **client);
void CanClientDestroy(struct CanClient *client);
int32_t CanClientWriteMsg(struct CanClient *client, const struct CanMsg *msg);
int32_t CanClientReadMsg(struct CanClient *client, struct CanMsg *msg, uint32_t tms);
int32_t CanClientAddFilter(struct CanClient *client, const struct CanFilter *filter);
int32_t CanClientDelFilter(struct CanClient *client, const struct CanFilter *filter);
int32_t CanClientSetCfg(struct CanClient *client, const struct CanConfig *cfg);
int32_t CanClientGetCfg(struct CanClient *client, struct CanConfig *cfg);
int32_t CanClientGetState(struct CanClient *client);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+108
View File
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef CAN_CORE_H
#define CAN_CORE_H
#include "can_if.h"
#include "can_manager.h"
#include "can_msg.h"
#include "can_service.h"
#include "hdf_base.h"
#include "hdf_dlist.h"
#include "hdf_sref.h"
#include "osal_mutex.h"
#include "platform_core.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct CanCntlr;
struct CanRxBox;
struct CanCntlrMethod {
int32_t (*open)(struct CanCntlr *cntlr);
int32_t (*close)(struct CanCntlr *cntlr);
int32_t (*lock)(struct CanCntlr *cntlr);
int32_t (*unlock)(struct CanCntlr *cntlr);
int32_t (*sendMsg)(struct CanCntlr *cntlr, const struct CanMsg *msg);
int32_t (*setCfg)(struct CanCntlr *cntlr, const struct CanConfig *cfg);
int32_t (*getCfg)(struct CanCntlr *cntlr, struct CanConfig *cfg);
int32_t (*getState)(struct CanCntlr *cntlr);
int32_t (*addFilter)(struct CanCntlr *cntlr, struct CanFilter *filter);
int32_t (*delFilter)(struct CanCntlr *cntlr, struct CanFilter *filter);
};
struct CanCntlr {
struct PlatformDevice device; // common father
struct OsalMutex lock; // running lock
int32_t number; // bus number
int32_t speed; // bit rate
int32_t state; // bus status
int32_t mode; // work mode
struct CanCntlrMethod *ops;
struct DListHead filters;
struct DListHead rxBoxList;
struct OsalMutex rboxListLock;
};
struct CanFilterNode {
const struct CanFilter *filter;
struct DListHead node;
bool active;
};
enum CanErrState {
CAN_ERR_ACTIVE, // error active CAN_ERR_PASSIVE, // error passive
CAN_ERR_BUS_OFF, // error bus off
};
struct CanTiming {
uint32_t brp; // prescaler
uint32_t sjw; // sync jump width
uint32_t seg1; // phase segment 1
uint32_t seg2; // phase segment 2
};
// HDF dev relationship manage
static inline int32_t CanCntlrSetHdfDev(struct CanCntlr *cntlr, struct HdfDeviceObject *device)
{
return PlatformDeviceSetHdfDev(&cntlr->device, device);
}
static inline struct CanCntlr *CanCntlrFromHdfDev(struct HdfDeviceObject *device)
{
struct PlatformDevice *pdevice = PlatformDeviceFromHdfDev(device);
return (pdevice == NULL) ? NULL : CONTAINER_OF(pdevice, struct CanCntlr, device);
}
// CAN BUS operations
int32_t CanCntlrWriteMsg(struct CanCntlr *cntlr, const struct CanMsg *msg);
int32_t CanCntlrAddFilter(struct CanCntlr *cntlr, struct CanFilter *filter);
int32_t CanCntlrDelFilter(struct CanCntlr *cntlr, struct CanFilter *filter);
int32_t CanCntlrSetCfg(struct CanCntlr *cntlr, const struct CanConfig *cfg);
int32_t CanCntlrGetCfg(struct CanCntlr *cntlr, struct CanConfig *cfg);
int32_t CanCntlrGetState(struct CanCntlr *cntlr);
int32_t CanCntlrOnNewMsg(struct CanCntlr *cntlr, struct CanMsg *msg);
int32_t CanCntlrAddRxBox(struct CanCntlr *cntlr, struct CanRxBox *rxBox);
int32_t CanCntlrDelRxBox(struct CanCntlr *cntlr, struct CanRxBox *rxBox);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef CAN_MAIL_H
#define CAN_MAIL_H
#include "can_core.h"
#include "can_msg.h"
#include "platform_queue.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct CanRxBox {
struct PlatformQueue *queue;
struct DListHead node;
struct DListHead filters;
OsalSpinlock spin;
};
struct CanRxBox *CanRxBoxCreate(void);
void CanRxBoxDestroy(struct CanRxBox *rbox);
static inline void CanRxBoxLock(struct CanRxBox *rbox)
{
(void)OsalSpinLock(&rbox->spin);
}
static inline void CanRxBoxUnlock(struct CanRxBox *rbox)
{
(void)OsalSpinUnlock(&rbox->spin);
}
int32_t CanRxBoxAddMsg(struct CanRxBox *rbox, struct CanMsg *cmsg);
int32_t CanRxBoxGetMsg(struct CanRxBox *rbox, struct CanMsg **cmsg, uint32_t tms);
int32_t CanRxBoxAddFilter(struct CanRxBox *rbox, const struct CanFilter *filter);
int32_t CanRxBoxDelFilter(struct CanRxBox *rbox, const struct CanFilter *filter);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef CAN_MANAGER_H
#define CAN_MANAGER_H
#include "hdf_base.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct CanCntlr;
// CAN BUS controller manage
int32_t CanCntlrAdd(struct CanCntlr *cntlr);
int32_t CanCntlrDel(struct CanCntlr *cntlr);
void CanCntlrPut(struct CanCntlr *cntlr);
struct CanCntlr *CanCntlrGetByName(const char *name);
struct CanCntlr *CanCntlrGetByNumber(int32_t number);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef CAN_MSG_H
#define CAN_MSG_H
#include "can_if.h"
#include "hdf_sref.h"
#include "platform_queue.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct CanMsg *CanMsgObtain(void);
void CanMsgRecycle(struct CanMsg *msg);
void CanMsgGet(struct CanMsg *msg);
void CanMsgPut(struct CanMsg *msg);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef CAN_SERVICE_H
#define CAN_SERVICE_H
#include "hdf_device_desc.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
enum CanIoCmd {
CAN_IO_READ = 0,
CAN_IO_WRITE = 1,
CAN_IO_SETCFG = 2,
CAN_IO_GETCFG = 3,
};
int32_t CanServiceBind(struct HdfDeviceObject *device);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CAN_SERVICE_H */
+164
View File
@@ -0,0 +1,164 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "can/can_client.h"
#include "can/can_msg.h"
#include "osal_mem.h"
#include "securec.h"
struct CanClient {
struct CanCntlr *cntlr;
struct CanRxBox *rxBox; // receive message box
};
static int32_t CanClientAttach(struct CanClient *client, struct CanCntlr *cntlr)
{
int32_t ret;
ret = CanCntlrAddRxBox(cntlr, client->rxBox);
if (ret == HDF_SUCCESS) {
client->cntlr = cntlr;
}
return ret;
}
static int32_t CanClientDetach(struct CanClient *client)
{
int32_t ret;
ret = CanCntlrDelRxBox(client->cntlr, client->rxBox);
if (ret == HDF_SUCCESS) {
client->cntlr = NULL;
}
return ret;
}
static int32_t CanClientCreate(struct CanCntlr *cntlr, struct CanClient **client)
{
int32_t ret;
struct CanClient *new = NULL;
new = (struct CanClient *)OsalMemCalloc(sizeof(*new));
if (new == NULL) {
return HDF_ERR_MALLOC_FAIL;
}
new->rxBox = CanRxBoxCreate();
if (new->rxBox == NULL) {
OsalMemFree(new);
return HDF_ERR_MALLOC_FAIL;
}
ret = CanClientAttach(new, cntlr);
if (ret != HDF_SUCCESS) {
CanRxBoxDestroy(new->rxBox);
OsalMemFree(new);
return ret;
}
*client = new;
return HDF_SUCCESS;
}
int32_t CanClientCreateByNumber(int32_t busNum, struct CanClient **client)
{
int32_t ret;
struct CanCntlr *cntlr = NULL;
cntlr = CanCntlrGetByNumber(busNum);
if (cntlr == NULL) {
return HDF_PLT_ERR_DEV_GET;
}
ret = CanClientCreate(cntlr, client);
if (ret != HDF_SUCCESS) {
CanCntlrPut(cntlr);
return ret;
}
return HDF_SUCCESS;
}
void CanClientDestroy(struct CanClient *client)
{
struct CanCntlr *cntlr = NULL;
if (client != NULL) {
cntlr = client->cntlr;
CanClientDetach(client);
CanCntlrPut(cntlr);
CanRxBoxDestroy(client->rxBox);
OsalMemFree(client);
}
}
int32_t CanClientWriteMsg(struct CanClient *client, const struct CanMsg *msg)
{
if (client == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
return CanCntlrWriteMsg(client->cntlr, msg);
}
int32_t CanClientReadMsg(struct CanClient *client, struct CanMsg *msg, uint32_t tms)
{
int32_t ret;
struct CanMsg *cmsg = NULL;
if (client == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
ret = CanRxBoxGetMsg(client->rxBox, &cmsg, tms);
if (ret != HDF_SUCCESS) {
return ret;
}
ret = memcpy_s(msg, sizeof(*msg), cmsg, sizeof(*cmsg));
CanMsgPut(cmsg); // decrease ref cnt after mem cpoy
return (ret == EOK) ? HDF_SUCCESS : HDF_ERR_IO;
}
int32_t CanClientAddFilter(struct CanClient *client, const struct CanFilter *filter)
{
if (client == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
return CanRxBoxAddFilter(client->rxBox, filter);
}
int32_t CanClientDelFilter(struct CanClient *client, const struct CanFilter *filter)
{
if (client == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
return CanRxBoxDelFilter(client->rxBox, filter);
}
int32_t CanClientSetCfg(struct CanClient *client, const struct CanConfig *cfg)
{
if (client == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
return CanCntlrSetCfg(client->cntlr, cfg);
}
int32_t CanClientGetCfg(struct CanClient *client, struct CanConfig *cfg)
{
if (client == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
return CanCntlrGetCfg(client->cntlr, cfg);
}
int32_t CanClientGetState(struct CanClient *client)
{
if (client == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
return CanCntlrGetState(client->cntlr);
}
+199
View File
@@ -0,0 +1,199 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "can/can_core.h"
#include "can/can_mail.h"
#include "can/can_msg.h"
static int32_t CanCntlrLock(struct CanCntlr *cntlr)
{
if (cntlr->ops != NULL && cntlr->ops->lock != NULL) {
return cntlr->ops->lock(cntlr);
} else {
return OsalMutexLock(&cntlr->lock);
}
}
static void CanCntlrUnlock(struct CanCntlr *cntlr)
{
if (cntlr->ops != NULL && cntlr->ops->unlock != NULL) {
cntlr->ops->unlock(cntlr);
} else {
(void)OsalMutexUnlock(&cntlr->lock);
}
}
int32_t CanCntlrWriteMsg(struct CanCntlr *cntlr, const struct CanMsg *msg)
{
int32_t ret;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (cntlr->ops == NULL || cntlr->ops->sendMsg == NULL) {
return HDF_ERR_NOT_SUPPORT;
}
if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
return ret;
}
ret = cntlr->ops->sendMsg(cntlr, msg);
CanCntlrUnlock(cntlr);
return ret;
}
int32_t CanCntlrAddFilter(struct CanCntlr *cntlr, struct CanFilter *filter)
{
int32_t ret;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (cntlr->ops == NULL || cntlr->ops->addFilter == NULL) {
return HDF_ERR_NOT_SUPPORT;
}
if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
return ret;
}
ret = cntlr->ops->addFilter(cntlr, filter);
CanCntlrUnlock(cntlr);
return ret;
}
int32_t CanCntlrDelFilter(struct CanCntlr *cntlr, struct CanFilter *filter)
{
int32_t ret;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (cntlr->ops == NULL || cntlr->ops->delFilter == NULL) {
return HDF_ERR_NOT_SUPPORT;
}
if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
return ret;
}
ret = cntlr->ops->delFilter(cntlr, filter);
CanCntlrUnlock(cntlr);
return ret;
}
int32_t CanCntlrSetCfg(struct CanCntlr *cntlr, const struct CanConfig *cfg)
{
int32_t ret;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (cntlr->ops == NULL || cntlr->ops->setCfg == NULL) {
return HDF_ERR_NOT_SUPPORT;
}
if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
return ret;
}
ret = cntlr->ops->setCfg(cntlr, cfg);
CanCntlrUnlock(cntlr);
return ret;
}
int32_t CanCntlrGetCfg(struct CanCntlr *cntlr, struct CanConfig *cfg)
{
int32_t ret;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (cntlr->ops == NULL || cntlr->ops->getCfg == NULL) {
return HDF_ERR_NOT_SUPPORT;
}
if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
return ret;
}
ret = cntlr->ops->getCfg(cntlr, cfg);
CanCntlrUnlock(cntlr);
return ret;
}
int32_t CanCntlrGetState(struct CanCntlr *cntlr)
{
int32_t ret;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (cntlr->ops == NULL || cntlr->ops->getState == NULL) {
return HDF_ERR_NOT_SUPPORT;
}
if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
return ret;
}
ret = cntlr->ops->getState(cntlr);
CanCntlrUnlock(cntlr);
return ret;
}
int32_t CanCntlrAddRxBox(struct CanCntlr *cntlr, struct CanRxBox *rxBox)
{
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (rxBox == NULL) {
return HDF_ERR_INVALID_PARAM;
}
(void)OsalMutexLock(&cntlr->rboxListLock);
DListInsertTail(&rxBox->node, &cntlr->rxBoxList);
(void)OsalMutexUnlock(&cntlr->rboxListLock);
return HDF_SUCCESS;
}
int32_t CanCntlrDelRxBox(struct CanCntlr *cntlr, struct CanRxBox *rxBox)
{
struct CanRxBox *tmp = NULL;
struct CanRxBox *toRmv = NULL;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (rxBox == NULL) {
return HDF_ERR_INVALID_PARAM;
}
(void)OsalMutexLock(&cntlr->rboxListLock);
DLIST_FOR_EACH_ENTRY_SAFE(toRmv, tmp, &cntlr->rxBoxList, struct CanRxBox, node) {
if (toRmv == rxBox) {
DListRemove(&toRmv->node);
(void)OsalMutexUnlock(&cntlr->rboxListLock);
return HDF_SUCCESS;
}
}
(void)OsalMutexUnlock(&cntlr->rboxListLock);
return HDF_ERR_NOT_SUPPORT;
}
static int32_t CanCntlrMsgDispatch(struct CanCntlr *cntlr, struct CanMsg *msg)
{
struct CanRxBox *rxBox = NULL;
(void)OsalMutexLock(&cntlr->rboxListLock);
DLIST_FOR_EACH_ENTRY(rxBox, &cntlr->rxBoxList, struct CanRxBox, node) {
(void)CanRxBoxAddMsg(rxBox, msg);
}
(void)OsalMutexUnlock(&cntlr->rboxListLock);
CanMsgPut(msg);
return HDF_SUCCESS;
}
int32_t CanCntlrOnNewMsg(struct CanCntlr *cntlr, struct CanMsg *msg)
{
return CanCntlrMsgDispatch(cntlr, msg); // gona call in thread context later ...
}
+63
View File
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "can_if.h"
#include "can/can_client.h"
#include "can/can_core.h"
int32_t CanBusOpen(int32_t number, DevHandle *handle)
{
int32_t ret;
struct CanClient *client = NULL;
ret = CanClientCreateByNumber(number, &client);
if (ret == HDF_SUCCESS) {
*handle = (DevHandle)client;
}
return ret;
}
void CanBusClose(DevHandle handle)
{
CanClientDestroy((struct CanClient *)handle);
}
int32_t CanBusSendMsg(DevHandle handle, const struct CanMsg *msg)
{
return CanClientWriteMsg((struct CanClient *)handle, msg);
}
int32_t CanBusReadMsg(DevHandle handle, struct CanMsg *msg, uint32_t tms)
{
return CanClientReadMsg((struct CanClient *)handle, msg, tms);
}
int32_t CanBusAddFilter(DevHandle handle, const struct CanFilter *filter)
{
return CanClientAddFilter((struct CanClient *)handle, filter);
}
int32_t CanBusDelFilter(DevHandle handle, const struct CanFilter *filter)
{
return CanClientDelFilter((struct CanClient *)handle, filter);
}
int32_t CanBusSetCfg(DevHandle handle, const struct CanConfig *cfg)
{
return CanClientSetCfg((struct CanClient *)handle, cfg);
}
int32_t CanBusGetCfg(DevHandle handle, struct CanConfig *cfg)
{
return CanClientGetCfg((struct CanClient *)handle, cfg);
}
int32_t CanBusGetState(DevHandle handle)
{
return CanClientGetState((struct CanClient *)handle);
}
+179
View File
@@ -0,0 +1,179 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "can/can_mail.h"
#include "can/can_msg.h"
#include "hdf_dlist.h"
#include "hdf_log.h"
#include "osal_mem.h"
struct CanRxBox *CanRxBoxCreate()
{
struct CanRxBox *rbox = NULL;
rbox = (struct CanRxBox *)OsalMemCalloc(sizeof(*rbox));
if (rbox == NULL) {
HDF_LOGE("CanRxBoxCreate: malloc failed");
return NULL;
}
rbox->queue = PlatformQueueCreate(NULL, "can_rbox", rbox);
if (rbox->queue == NULL) {
HDF_LOGE("CanRxBoxCreate: create rbox queue failed");
OsalMemFree(rbox);
return NULL;
}
DListHeadInit(&rbox->filters);
(void)OsalSpinInit(&rbox->spin);
return rbox;
}
void CanRxBoxDestroy(struct CanRxBox *rbox)
{
if (rbox != NULL) {
if (rbox->queue != NULL) {
PlatformQueueDestroy(rbox->queue);
}
OsalSpinDestroy(&rbox->spin);
OsalMemFree(rbox);
}
}
static bool CanRxBoxMsgMatch(struct CanRxBox *, const struct CanMsg *);
int32_t CanRxBoxAddMsg(struct CanRxBox *rbox, struct CanMsg *cmsg)
{
int32_t ret;
struct PlatformMsg *pmsg = NULL;
if (rbox == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (!CanRxBoxMsgMatch(rbox, cmsg)) {
return HDF_ERR_NOT_SUPPORT;
}
pmsg = (struct PlatformMsg *)OsalMemCalloc(sizeof(*pmsg));
if (pmsg == NULL) {
return HDF_ERR_MALLOC_FAIL;
}
pmsg->data = cmsg;
CanMsgGet(cmsg); // increase ref count before enqueue
ret = PlatformQueueAddMsg(rbox->queue, pmsg);
if (ret != HDF_SUCCESS) {
CanMsgPut(cmsg); // decrase ref count if enqueue failed
}
return ret;
}
int32_t CanRxBoxGetMsg(struct CanRxBox *rbox, struct CanMsg **cmsg, uint32_t tms)
{
int32_t ret;
struct PlatformMsg *pmsg = NULL;
if (rbox == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
ret = PlatformQueueGetMsg(rbox->queue, &pmsg, tms);
if (ret != HDF_SUCCESS) {
HDF_LOGE("CanRxBoxGetMsg: get platform msg failed:%d", ret);
return ret;
}
*cmsg = (struct CanMsg *)pmsg->data;
OsalMemFree(pmsg);
return HDF_SUCCESS;
}
static bool CanFilterMatch(const struct CanFilter *filter, const struct CanMsg *cmsg)
{
(void)filter;
(void)cmsg;
uint32_t mask;
if (filter->rtrMask == 1 && filter->rtr != cmsg->rtr) {
return false;
}
if (filter->ideMask == 1 && filter->ide != cmsg->ide) {
return false;
}
mask = (cmsg->ide == 1) ? 0x7FF : 0x1FFFFFFF; // 11bits or 29bits ?
mask &= filter->idMask;
return ((cmsg->id & mask) == (filter->id & mask));
}
static bool CanRxBoxMsgMatch(struct CanRxBox *rbox, const struct CanMsg *cmsg)
{
bool match = true;
struct CanFilterNode *cfNode = NULL;
if (rbox == NULL || cmsg == NULL) {
return false;
}
CanRxBoxLock(rbox);
DLIST_FOR_EACH_ENTRY(cfNode, &rbox->filters, struct CanFilterNode, node) {
if (CanFilterMatch(cfNode->filter, cmsg)) {
match = true;
break;
}
match = false;
}
CanRxBoxUnlock(rbox);
return match;
}
int32_t CanRxBoxAddFilter(struct CanRxBox *rbox, const struct CanFilter *filter)
{
struct CanFilterNode *cfNode = NULL;
if (rbox == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (filter == NULL) {
return HDF_ERR_INVALID_PARAM;
}
cfNode = (struct CanFilterNode *)OsalMemCalloc(sizeof(*cfNode));
if (cfNode == NULL) {
return HDF_ERR_MALLOC_FAIL;
}
cfNode->filter = filter;
cfNode->active = true;
CanRxBoxLock(rbox);
DListInsertTail(&cfNode->node, &rbox->filters);
CanRxBoxUnlock(rbox);
return HDF_SUCCESS;
}
int32_t CanRxBoxDelFilter(struct CanRxBox *rbox, const struct CanFilter *filter)
{
struct CanFilterNode *cfNode = NULL;
struct CanFilterNode *tmp = NULL;
if (rbox == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (filter == NULL) {
return HDF_ERR_INVALID_PARAM;
}
CanRxBoxLock(rbox);
DLIST_FOR_EACH_ENTRY_SAFE(cfNode, tmp, &rbox->filters, struct CanFilterNode, node) {
if (cfNode->filter == filter) {
DListRemove(&cfNode->node);
CanRxBoxUnlock(rbox);
OsalMemFree(cfNode);
return HDF_SUCCESS;
}
}
return HDF_ERR_NOT_SUPPORT;
}
+150
View File
@@ -0,0 +1,150 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "can/can_manager.h"
#include "can/can_core.h"
#define CAN_NUMBER_MAX 32
static struct PlatformManager *g_manager;
static struct PlatformManager *CanManagerGet(void)
{
int32_t ret;
if (g_manager == NULL) {
ret = PlatformManagerCreate("CAN_BUS_MANAGER", &g_manager);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: careate can bus manager failed:%d", __func__, ret);
}
}
return g_manager;
}
static void CanManagerDestroyIfNeed(void)
{
if (g_manager != NULL && DListIsEmpty(&g_manager->devices)) {
PlatformManagerDestroy(g_manager);
g_manager = NULL;
}
}
int32_t CanCntlrAdd(struct CanCntlr *cntlr)
{
int32_t ret;
if (cntlr == NULL || cntlr->ops == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (cntlr->number < 0 || cntlr->number >= CAN_NUMBER_MAX) {
HDF_LOGE("%s: can number %d invalid", __func__, cntlr->number);
return HDF_ERR_INVALID_OBJECT;
}
DListHeadInit(&cntlr->rxBoxList);
if (OsalMutexInit(&cntlr->lock) != HDF_SUCCESS) {
HDF_LOGE("CanCntlrAdd: init lock failed");
return HDF_FAILURE;
}
if (OsalMutexInit(&cntlr->rboxListLock) != HDF_SUCCESS) {
HDF_LOGE("CanCntlrAdd: init rx box list lock failed");
(void)OsalMutexDestroy(&cntlr->lock);
return HDF_FAILURE;
}
cntlr->device.number = cntlr->number;
ret = PlatformDeviceSetName(&cntlr->device, "CAN%d", cntlr->number);
if (ret != HDF_SUCCESS) {
(void)OsalMutexDestroy(&cntlr->rboxListLock);
(void)OsalMutexDestroy(&cntlr->lock);
return ret;
}
cntlr->device.manager = CanManagerGet();
if (cntlr->device.manager == NULL) {
PlatformDeviceClearName(&cntlr->device);
(void)OsalMutexDestroy(&cntlr->rboxListLock);
(void)OsalMutexDestroy(&cntlr->lock);
return HDF_PLT_ERR_DEV_GET;
}
if ((ret = PlatformDeviceAdd(&cntlr->device)) != HDF_SUCCESS) {
PlatformDeviceClearName(&cntlr->device);
(void)OsalMutexDestroy(&cntlr->rboxListLock);
(void)OsalMutexDestroy(&cntlr->lock);
return ret;
}
return HDF_SUCCESS;
}
int32_t CanCntlrDel(struct CanCntlr *cntlr)
{
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
PlatformDeviceDel(&cntlr->device);
PlatformDeviceClearName(&cntlr->device);
(void)OsalMutexDestroy(&cntlr->rboxListLock);
(void)OsalMutexDestroy(&cntlr->lock);
CanManagerDestroyIfNeed();
return HDF_SUCCESS;
}
static struct CanCntlr *CanCntlrFromPlatformDevice(struct PlatformDevice *pdevice)
{
return CONTAINER_OF(pdevice, struct CanCntlr, device);
}
struct CanCntlr *CanCntlrGetByName(const char *name)
{
static struct PlatformManager *manager = NULL;
struct PlatformDevice *pdevice = NULL;
manager = CanManagerGet();
if (manager == NULL) {
return NULL;
}
pdevice = PlatformManagerGetDeviceByName(manager, name);
if (pdevice == NULL) {
return NULL;
}
return CanCntlrFromPlatformDevice(pdevice);
}
struct CanCntlr *CanCntlrGetByNumber(int32_t number)
{
static struct PlatformManager *manager = NULL;
struct PlatformDevice *pdevice = NULL;
manager = CanManagerGet();
if (manager == NULL) {
return NULL;
}
pdevice = PlatformManagerGetDeviceByNumber(manager, number);
if (pdevice == NULL) {
return NULL;
}
return CanCntlrFromPlatformDevice(pdevice);
}
void CanCntlrPut(struct CanCntlr *cntlr)
{
if (cntlr != NULL) {
PlatformDevicePut(&cntlr->device);
}
}
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "can/can_msg.h"
#include "hdf_dlist.h"
#include "osal_mem.h"
struct CanMsgHolder {
struct HdfSRef ref;
struct CanMsg cmsg;
};
struct CanClient {
struct CanCntlr *cntlr;
struct CanRxBox *rxBox; // receive message box
};
static void CanMsgHolderOnFirstGet(struct HdfSRef *sref)
{
(void)sref;
}
static void CanMsgDoRecycle(struct CanMsg *msg)
{
struct CanMsgHolder *msgExt = NULL;
if (msg == NULL) {
return;
}
msgExt = CONTAINER_OF(msg, struct CanMsgHolder, cmsg);
OsalMemFree(msgExt);
}
static void CanMsgHolderOnLastPut(struct HdfSRef *sref)
{
struct CanMsgHolder *msgExt = NULL;
if (sref == NULL) {
return;
}
msgExt = CONTAINER_OF(sref, struct CanMsgHolder, ref);
CanMsgDoRecycle(&msgExt->cmsg);
}
struct IHdfSRefListener g_canMsgExtListener = {
.OnFirstAcquire = CanMsgHolderOnFirstGet,
.OnLastRelease = CanMsgHolderOnLastPut,
};
struct CanMsg *CanMsgObtain(void)
{
struct CanMsgHolder *msgExt = NULL;
msgExt = (struct CanMsgHolder *)OsalMemCalloc(sizeof(*msgExt));
if (msgExt == NULL) {
return NULL;
}
HdfSRefConstruct(&msgExt->ref, &g_canMsgExtListener);
CanMsgGet(&msgExt->cmsg);
return &msgExt->cmsg;
}
void CanMsgGet(struct CanMsg *msg)
{
struct CanMsgHolder *msgExt = NULL;
if (msg == NULL) {
return;
}
msgExt = CONTAINER_OF(msg, struct CanMsgHolder, cmsg);
HdfSRefAcquire(&msgExt->ref);
}
void CanMsgPut(struct CanMsg *msg)
{
struct CanMsgHolder *msgExt = NULL;
if (msg == NULL) {
return;
}
msgExt = CONTAINER_OF(msg, struct CanMsgHolder, cmsg);
HdfSRefRelease(&msgExt->ref);
}
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "can/can_service.h"
#include "can/can_core.h"
#include "hdf_device_desc.h"
#include "osal_mem.h"
#include "platform_core.h"
#define HDF_LOG_TAG can_service
static int32_t CanServiceDispatch(
struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
{
struct CanCntlr *cntlr = NULL;
(void)data;
(void)reply;
if (client == NULL || client->device == NULL) {
HDF_LOGE("CanServiceDispatch: invalid client object!");
return HDF_ERR_INVALID_OBJECT;
}
cntlr = CanCntlrFromHdfDev(client->device);
if (cntlr == NULL) {
HDF_LOGE("CanServiceDispatch: no controller binded!");
return HDF_ERR_INVALID_OBJECT;
}
HDF_LOGD("CanServiceDispatch: cntlr number=%d, cmd = %d", cntlr->number, cmd);
return HDF_SUCCESS;
}
int32_t CanServiceBind(struct HdfDeviceObject *device)
{
struct IDeviceIoService *service = NULL;
if (device == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
service = (struct IDeviceIoService *)OsalMemCalloc(sizeof(*service));
if (service == NULL) {
HDF_LOGE("CanServiceBind: alloc service failed!");
return HDF_ERR_MALLOC_FAIL;
}
service->Dispatch = CanServiceDispatch;
device->service = service;
return HDF_SUCCESS;
}