mirror of
https://github.com/openharmony/drivers_framework.git
synced 2026-08-26 18:17:07 -04:00
!934 Add CANBUS framework support on liteos
Merge pull request !934 from NickYang/master
This commit is contained in:
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 ...
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user