diff --git a/include/platform/can_if.h b/include/platform/can_if.h new file mode 100644 index 0000000000000000000000000000000000000000..a3b3ddd552802bc2b375bf4de0b6fffaba77bc2a --- /dev/null +++ b/include/platform/can_if.h @@ -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 */ diff --git a/support/platform/include/can/can_client.h b/support/platform/include/can/can_client.h new file mode 100644 index 0000000000000000000000000000000000000000..786fc046f79538639c63748df3e740ea8b5b1d90 --- /dev/null +++ b/support/platform/include/can/can_client.h @@ -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 diff --git a/support/platform/include/can/can_core.h b/support/platform/include/can/can_core.h new file mode 100644 index 0000000000000000000000000000000000000000..657cb315b248013773253624b091817d7984d135 --- /dev/null +++ b/support/platform/include/can/can_core.h @@ -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 diff --git a/support/platform/include/can/can_mail.h b/support/platform/include/can/can_mail.h new file mode 100644 index 0000000000000000000000000000000000000000..7e3d62e0aea6f164ee7da94adb78870cbf00b605 --- /dev/null +++ b/support/platform/include/can/can_mail.h @@ -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 diff --git a/support/platform/include/can/can_manager.h b/support/platform/include/can/can_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..b981527cc17c4b3cc4aa92f8d863e26d857912f6 --- /dev/null +++ b/support/platform/include/can/can_manager.h @@ -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 diff --git a/support/platform/include/can/can_msg.h b/support/platform/include/can/can_msg.h new file mode 100644 index 0000000000000000000000000000000000000000..4a5e0a36dee03dd729d4a88b5cf8d69f5a97d777 --- /dev/null +++ b/support/platform/include/can/can_msg.h @@ -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 diff --git a/support/platform/include/can/can_service.h b/support/platform/include/can/can_service.h new file mode 100644 index 0000000000000000000000000000000000000000..79fc89ca8d2a501694a657abbd8c8186a104e48f --- /dev/null +++ b/support/platform/include/can/can_service.h @@ -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 */ diff --git a/support/platform/src/can/can_client.c b/support/platform/src/can/can_client.c new file mode 100644 index 0000000000000000000000000000000000000000..0adb3112cfa8bc515e4a71e95c55d6d4142e3af7 --- /dev/null +++ b/support/platform/src/can/can_client.c @@ -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); +} diff --git a/support/platform/src/can/can_core.c b/support/platform/src/can/can_core.c new file mode 100644 index 0000000000000000000000000000000000000000..9b662c2257933b0514852c3f5ac1236a84e0a4ae --- /dev/null +++ b/support/platform/src/can/can_core.c @@ -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 ... +} diff --git a/support/platform/src/can/can_if.c b/support/platform/src/can/can_if.c new file mode 100644 index 0000000000000000000000000000000000000000..a717670ba523cc6952980824cf65707c69bb0832 --- /dev/null +++ b/support/platform/src/can/can_if.c @@ -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); +} diff --git a/support/platform/src/can/can_mail.c b/support/platform/src/can/can_mail.c new file mode 100644 index 0000000000000000000000000000000000000000..600673c9747c11eb05d914581a9ad5e2cc921e4c --- /dev/null +++ b/support/platform/src/can/can_mail.c @@ -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; +} diff --git a/support/platform/src/can/can_manager.c b/support/platform/src/can/can_manager.c new file mode 100644 index 0000000000000000000000000000000000000000..6a0b71b3b355306af03d10557b7bd41b5669bca4 --- /dev/null +++ b/support/platform/src/can/can_manager.c @@ -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); + } +} diff --git a/support/platform/src/can/can_msg.c b/support/platform/src/can/can_msg.c new file mode 100644 index 0000000000000000000000000000000000000000..2d4fc1bd075f4ddad72db344d86c61d8ea0a58c5 --- /dev/null +++ b/support/platform/src/can/can_msg.c @@ -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); +} diff --git a/support/platform/src/can/can_service.c b/support/platform/src/can/can_service.c new file mode 100644 index 0000000000000000000000000000000000000000..4b003e223cc089fb03bf7c84166502fb4375865d --- /dev/null +++ b/support/platform/src/can/can_service.c @@ -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; +}