1 /*
2 * Copyright (c) 2020-2023 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "pwm_core.h"
10 #include "hdf_log.h"
11 #include "securec.h"
12
13 #define HDF_LOG_TAG pwm_core
14
PwmDeviceGet(struct PwmDev * pwm)15 int32_t PwmDeviceGet(struct PwmDev *pwm)
16 {
17 int32_t ret;
18
19 if (pwm == NULL) {
20 HDF_LOGE("PwmDeviceGet: pwm is null!\n");
21 return HDF_ERR_INVALID_PARAM;
22 }
23
24 (void)OsalSpinLock(&(pwm->lock));
25 if (pwm->busy) {
26 (void)OsalSpinUnlock(&(pwm->lock));
27 HDF_LOGE("PwmDeviceGet: pwm%u is busy!", pwm->num);
28 return HDF_ERR_DEVICE_BUSY;
29 }
30 if (pwm->method != NULL && pwm->method->open != NULL) {
31 ret = pwm->method->open(pwm);
32 if (ret != HDF_SUCCESS) {
33 (void)OsalSpinUnlock(&(pwm->lock));
34 HDF_LOGE("PwmDeviceGet: open fail, ret: %d!", ret);
35 return HDF_FAILURE;
36 }
37 }
38
39 pwm->busy = true;
40 (void)OsalSpinUnlock(&(pwm->lock));
41 return HDF_SUCCESS;
42 }
43
PwmDevicePut(struct PwmDev * pwm)44 int32_t PwmDevicePut(struct PwmDev *pwm)
45 {
46 int32_t ret;
47
48 if (pwm == NULL) {
49 HDF_LOGE("PwmDevicePut: pwm is null!\n");
50 return HDF_ERR_INVALID_PARAM;
51 }
52
53 if (pwm->method != NULL && pwm->method->close != NULL) {
54 ret = pwm->method->close(pwm);
55 if (ret != HDF_SUCCESS) {
56 HDF_LOGE("PwmDevicePut: close fail, ret: %d!", ret);
57 return ret;
58 }
59 }
60 (void)OsalSpinLock(&(pwm->lock));
61 pwm->busy = false;
62 (void)OsalSpinUnlock(&(pwm->lock));
63 return HDF_SUCCESS;
64 }
65
PwmDeviceSetConfig(struct PwmDev * pwm,struct PwmConfig * config)66 int32_t PwmDeviceSetConfig(struct PwmDev *pwm, struct PwmConfig *config)
67 {
68 int32_t ret;
69
70 if (pwm == NULL || config == NULL) {
71 HDF_LOGE("PwmDeviceSetConfig: pwm or config is null!\n");
72 return HDF_ERR_INVALID_PARAM;
73 }
74
75 if (memcmp(config, &(pwm->cfg), sizeof(*config)) == 0) {
76 HDF_LOGE("PwmDeviceSetConfig: do not need to set config!");
77 return HDF_SUCCESS;
78 }
79
80 if (pwm->method == NULL || pwm->method->setConfig == NULL) {
81 HDF_LOGE("PwmDeviceSetConfig: method or setConfig is null!");
82 return HDF_ERR_NOT_SUPPORT;
83 }
84
85 ret = pwm->method->setConfig(pwm, config);
86 if (ret != HDF_SUCCESS) {
87 HDF_LOGE("PwmDeviceSetConfig: set config fail, ret: %d!", ret);
88 return ret;
89 }
90
91 (void)OsalSpinLock(&(pwm->lock));
92 pwm->cfg = *config;
93 (void)OsalSpinUnlock(&(pwm->lock));
94 return HDF_SUCCESS;
95 }
96
PwmDeviceGetConfig(struct PwmDev * pwm,struct PwmConfig * config)97 int32_t PwmDeviceGetConfig(struct PwmDev *pwm, struct PwmConfig *config)
98 {
99 if (pwm == NULL || config == NULL) {
100 HDF_LOGE("PwmDeviceGetConfig: pwm or config is null!\n");
101 return HDF_ERR_INVALID_PARAM;
102 }
103
104 (void)OsalSpinLock(&(pwm->lock));
105 *config = pwm->cfg;
106 (void)OsalSpinUnlock(&(pwm->lock));
107 return HDF_SUCCESS;
108 }
109
PwmSetPriv(struct PwmDev * pwm,void * priv)110 int32_t PwmSetPriv(struct PwmDev *pwm, void *priv)
111 {
112 if (pwm == NULL) {
113 HDF_LOGE("PwmSetPriv: pwm is null!");
114 return HDF_ERR_INVALID_PARAM;
115 }
116
117 (void)OsalSpinLock(&(pwm->lock));
118 pwm->priv = priv;
119 (void)OsalSpinUnlock(&(pwm->lock));
120 return HDF_SUCCESS;
121 }
122
PwmGetPriv(const struct PwmDev * pwm)123 void *PwmGetPriv(const struct PwmDev *pwm)
124 {
125 if (pwm == NULL) {
126 HDF_LOGE("PwmGetPriv: pwm is null!");
127 return NULL;
128 }
129 return pwm->priv;
130 }
131
PwmUserSetConfig(struct PwmDev * pwm,struct HdfSBuf * data)132 static int32_t PwmUserSetConfig(struct PwmDev *pwm, struct HdfSBuf *data)
133 {
134 uint32_t size;
135 struct PwmConfig *config = NULL;
136
137 if (data == NULL) {
138 HDF_LOGE("PwmUserSetConfig: data is null!");
139 return HDF_ERR_INVALID_PARAM;
140 }
141 if (!HdfSbufReadBuffer(data, (const void **)&config, &size)) {
142 HDF_LOGE("PwmUserSetConfig: sbuf read buffer fail!");
143 return HDF_ERR_IO;
144 }
145
146 if ((config == NULL) || (size != sizeof(struct PwmConfig))) {
147 HDF_LOGE("PwmUserSetConfig: read buff error!");
148 return HDF_ERR_IO;
149 }
150 return PwmDeviceSetConfig(pwm, config);
151 }
152
PwmUserGetConfig(struct PwmDev * pwm,struct HdfSBuf * reply)153 static int32_t PwmUserGetConfig(struct PwmDev *pwm, struct HdfSBuf *reply)
154 {
155 int32_t ret;
156 struct PwmConfig config;
157
158 if (reply == NULL) {
159 HDF_LOGE("PwmUserGetConfig: reply is null!");
160 return HDF_ERR_INVALID_PARAM;
161 }
162 ret = PwmDeviceGetConfig(pwm, &config);
163 if (ret != HDF_SUCCESS) {
164 HDF_LOGE("PwmUserGetConfig: get config fail!");
165 return ret;
166 }
167
168 if (!HdfSbufWriteBuffer(reply, &config, sizeof(config))) {
169 HDF_LOGE("PwmUserGetConfig: sbuf write buffer fail!");
170 return HDF_ERR_IO;
171 }
172 return HDF_SUCCESS;
173 }
174
PwmIoDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)175 static int32_t PwmIoDispatch(struct HdfDeviceIoClient *client, int cmd,
176 struct HdfSBuf *data, struct HdfSBuf *reply)
177 {
178 struct PwmDev *pwm = NULL;
179
180 if (client == NULL || client->device == NULL || client->device->service == NULL) {
181 HDF_LOGE("PwmIoDispatch: client info is null!");
182 return HDF_ERR_INVALID_OBJECT;
183 }
184
185 pwm = (struct PwmDev *)client->device->service;
186 switch (cmd) {
187 case PWM_IO_GET:
188 return PwmDeviceGet(pwm);
189 case PWM_IO_PUT:
190 return PwmDevicePut(pwm);
191 case PWM_IO_SET_CONFIG:
192 return PwmUserSetConfig(pwm, data);
193 case PWM_IO_GET_CONFIG:
194 return PwmUserGetConfig(pwm, reply);
195 default:
196 HDF_LOGE("PwmIoDispatch: cmd %d is not support!", cmd);
197 return HDF_ERR_NOT_SUPPORT;
198 }
199 }
200
PwmDeviceAdd(struct HdfDeviceObject * obj,struct PwmDev * pwm)201 int32_t PwmDeviceAdd(struct HdfDeviceObject *obj, struct PwmDev *pwm)
202 {
203 if (obj == NULL || pwm == NULL) {
204 HDF_LOGE("PwmDeviceAdd: obj or pwm is null!");
205 return HDF_ERR_INVALID_PARAM;
206 }
207 if (pwm->method == NULL || pwm->method->setConfig == NULL) {
208 HDF_LOGE("PwmDeviceAdd: method or setConfig is null!");
209 return HDF_ERR_INVALID_PARAM;
210 }
211 if (OsalSpinInit(&(pwm->lock)) != HDF_SUCCESS) {
212 HDF_LOGE("PwmDeviceAdd: init spinlock fail!");
213 return HDF_FAILURE;
214 }
215 pwm->device = obj;
216 obj->service = &(pwm->service);
217 pwm->device->service->Dispatch = PwmIoDispatch;
218 return HDF_SUCCESS;
219 }
220
PwmDeviceRemove(struct HdfDeviceObject * obj,struct PwmDev * pwm)221 void PwmDeviceRemove(struct HdfDeviceObject *obj, struct PwmDev *pwm)
222 {
223 if (obj == NULL || pwm == NULL) {
224 HDF_LOGE("PwmDeviceRemove: obj or pwm is null!");
225 return;
226 }
227 (void)OsalSpinDestroy(&(pwm->lock));
228 pwm->device = NULL;
229 obj->service = NULL;
230 }
231