1 /*
2 * Copyright (c) 2021-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 "hdmi_dispatch.h"
10 #include "hdf_log.h"
11 #include "hdmi_core.h"
12 #include "hdmi_if.h"
13
14 #define HDF_LOG_TAG hdmi_dispatch_c
15
16 enum HdmiIoCmd {
17 HDMI_CMD_OPEN,
18 HDMI_CMD_CLOSE,
19 HDMI_CMD_START,
20 HDMI_CMD_STOP,
21 HDMI_CMD_AVMUTE_SET,
22 HDMI_CMD_DEEP_COLOR_SET,
23 HDMI_CMD_DEEP_COLOR_GET,
24 HDMI_CMD_VIDEO_ATTR_SET,
25 HDMI_CMD_AUDIO_ATTR_SET,
26 HDMI_CMD_HDR_ATTR_SET,
27 HDMI_CMD_READ_SINK_EDID,
28 HDMI_CMD_INFOFRAME_SET,
29 HDMI_CMD_INFOFRAME_GET,
30 HDMI_CMD_REGISTER_HPD_CALLBACK_FUNC,
31 HDMI_CMD_UNREGISTER_HPD_CALLBACK_FUNC,
32 HDMI_CMD_BUTT,
33 };
34
35 struct HdmiDispatchFunc {
36 uint32_t cmd;
37 int32_t (*func)(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply);
38 };
39
HdmiCmdOpen(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)40 static int32_t HdmiCmdOpen(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
41 {
42 (void)data;
43 (void)reply;
44
45 return HdmiCntlrOpen(cntlr);
46 }
47
HdmiCmdClose(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)48 static int32_t HdmiCmdClose(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
49 {
50 (void)data;
51 (void)reply;
52
53 HdmiCntlrClose(cntlr);
54 return HDF_SUCCESS;
55 }
56
HdmiCmdStart(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)57 static int32_t HdmiCmdStart(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
58 {
59 (void)data;
60 (void)reply;
61
62 return HdmiCntlrStart(cntlr);
63 }
64
HdmiCmdStop(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)65 static int32_t HdmiCmdStop(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
66 {
67 (void)data;
68 (void)reply;
69
70 return HdmiCntlrStop(cntlr);
71 }
72
HdmiCmdAvmuteSet(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)73 static int32_t HdmiCmdAvmuteSet(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
74 {
75 bool *enable = NULL;
76 size_t size;
77 (void)reply;
78
79 if (!HdfSbufReadBuffer(data, (const void **)&enable, &size)) {
80 HDF_LOGE("HdmiCmdAvmuteSet: sbuf read buffer failed");
81 return HDF_ERR_IO;
82 }
83 HdmiCntlrAvmuteSet(cntlr, *enable);
84 return HDF_SUCCESS;
85 }
86
HdmiCmdDeepColorSet(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)87 static int32_t HdmiCmdDeepColorSet(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
88 {
89 enum HdmiDeepColor *color = NULL;
90 size_t size;
91 (void)reply;
92
93 if (!HdfSbufReadBuffer(data, (const void **)&color, &size)) {
94 HDF_LOGE("HdmiCmdDeepColorSet: sbuf read buffer failed");
95 return HDF_ERR_IO;
96 }
97 return HdmiCntlrDeepColorSet(cntlr, *color);
98 }
99
HdmiCmdDeepColorGet(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)100 static int32_t HdmiCmdDeepColorGet(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
101 {
102 int32_t ret;
103 enum HdmiDeepColor color;
104 (void)data;
105
106 if (reply == NULL) {
107 return HDF_ERR_INVALID_PARAM;
108 }
109
110 ret = HdmiCntlrDeepColorGet(cntlr, &color);
111 if (ret != HDF_SUCCESS) {
112 return ret;
113 }
114
115 if (HdfSbufWriteBuffer(reply, &color, sizeof(color)) == false) {
116 HDF_LOGE("HdmiCmdDeepColorGet: write back color fail!");
117 return HDF_ERR_IO;
118 }
119 return HDF_SUCCESS;
120 }
121
HdmiCmdVideoAttrSet(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)122 static int32_t HdmiCmdVideoAttrSet(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
123 {
124 struct HdmiVideoAttr *attr = NULL;
125 size_t size;
126 (void)reply;
127
128 if (!HdfSbufReadBuffer(data, (const void **)&attr, &size)) {
129 HDF_LOGE("HdmiCmdVideoAttrSet: sbuf read buffer failed");
130 return HDF_ERR_IO;
131 }
132 return HdmiCntlrSetVideoAttribute(cntlr, attr);
133 }
134
HdmiCmdAudioAttrSet(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)135 static int32_t HdmiCmdAudioAttrSet(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
136 {
137 struct HdmiAudioAttr *attr = NULL;
138 size_t size;
139 (void)reply;
140
141 if (!HdfSbufReadBuffer(data, (const void **)&attr, &size)) {
142 HDF_LOGE("HdmiCmdAudioAttrSet: sbuf read buffer failed");
143 return HDF_ERR_IO;
144 }
145 return HdmiCntlrSetAudioAttribute(cntlr, attr);
146 }
147
HdmiCmdHdrAttrSet(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)148 static int32_t HdmiCmdHdrAttrSet(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
149 {
150 struct HdmiHdrAttr *attr = NULL;
151 size_t size;
152 (void)reply;
153
154 if (!HdfSbufReadBuffer(data, (const void **)&attr, &size)) {
155 HDF_LOGE("HdmiCmdHdrAttrSet: sbuf read buffer failed");
156 return HDF_ERR_IO;
157 }
158 return HdmiCntlrSetHdrAttribute(cntlr, attr);
159 }
160
HdmiCmdReadSinkEdid(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)161 static int32_t HdmiCmdReadSinkEdid(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
162 {
163 int32_t ret;
164 uint8_t edid[HDMI_EDID_TOTAL_SIZE] = {0};
165 (void)data;
166
167 if (reply == NULL) {
168 return HDF_ERR_INVALID_PARAM;
169 }
170
171 ret = HdmiCntlrGetSinkEdid(cntlr, edid, HDMI_EDID_TOTAL_SIZE);
172 if (ret != HDF_SUCCESS) {
173 return ret;
174 }
175
176 if (HdfSbufWriteBuffer(reply, edid, HDMI_EDID_TOTAL_SIZE) == false) {
177 HDF_LOGE("HdmiCmdReadSinkEdid: write back edid fail!");
178 return HDF_ERR_IO;
179 }
180
181 return HDF_SUCCESS;
182 }
183
HdmiCmdInfoFrameSet(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)184 static int32_t HdmiCmdInfoFrameSet(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
185 {
186 enum HdmiPacketType type;
187 union HdmiInfoFrameInfo *frame = NULL;
188 size_t size;
189
190 (void)reply;
191 if (!HdfSbufReadUint16(data, (uint16_t *)&type)) {
192 HDF_LOGE("HdmiCmdInfoFrameSet: sbuf read uint16 failed");
193 return HDF_ERR_IO;
194 }
195
196 if (!HdfSbufReadBuffer(data, (const void **)&frame, &size)) {
197 HDF_LOGE("HdmiCmdInfoFrameSet: sbuf read buffer failed");
198 return HDF_ERR_IO;
199 }
200 return HdmiCntlrInfoFrameSet(cntlr, type, frame);
201 }
202
HdmiCmdInfoFrameGet(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)203 static int32_t HdmiCmdInfoFrameGet(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
204 {
205 size_t size;
206 int32_t ret;
207 enum HdmiPacketType *type = NULL;
208 union HdmiInfoFrameInfo frame = {0};
209
210 if (!HdfSbufReadBuffer(data, (const void **)&type, &size)) {
211 HDF_LOGE("HdmiCmdInfoFrameGet: sbuf read buffer failed");
212 return HDF_ERR_IO;
213 }
214
215 ret = HdmiCntlrInfoFrameGet(cntlr, *type, &frame);
216 if (ret != HDF_SUCCESS) {
217 return ret;
218 }
219
220 if (HdfSbufWriteBuffer(reply, &frame, sizeof(frame)) == false) {
221 HDF_LOGE("HdmiCmdInfoFrameGet: write back frame fail!");
222 return HDF_ERR_IO;
223 }
224
225 return HDF_SUCCESS;
226 }
227
HdmiCmdRegisterHpdCallbackFunc(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)228 static int32_t HdmiCmdRegisterHpdCallbackFunc(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
229 {
230 uint32_t *addr = NULL;
231 size_t size;
232 (void)reply;
233
234 if (!HdfSbufReadBuffer(data, (const void **)&addr, &size)) {
235 HDF_LOGE("HdmiCmdRegisterHpdCallbackFunc: sbuf read buffer failed");
236 return HDF_ERR_IO;
237 }
238 return HdmiCntlrRegisterHpdCallbackFunc(cntlr, (struct HdmiHpdCallbackInfo *)(uintptr_t)(*addr));
239 }
240
HdmiCmdUnregisterHpdCallbackFunc(struct HdmiCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)241 static int32_t HdmiCmdUnregisterHpdCallbackFunc(struct HdmiCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
242 {
243 (void)data;
244 (void)reply;
245
246 return HdmiCntlrUnregisterHpdCallbackFunc(cntlr);
247 }
248
HdmiIoDispatch(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)249 int32_t HdmiIoDispatch(struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
250 {
251 struct HdmiCntlr *cntlr = NULL;
252 uint32_t i;
253 uint32_t len;
254 struct HdmiDispatchFunc dispatchFunc[] = {
255 { HDMI_CMD_OPEN, HdmiCmdOpen },
256 { HDMI_CMD_CLOSE, HdmiCmdClose },
257 { HDMI_CMD_START, HdmiCmdStart },
258 { HDMI_CMD_STOP, HdmiCmdStop },
259 { HDMI_CMD_AVMUTE_SET, HdmiCmdAvmuteSet },
260 { HDMI_CMD_DEEP_COLOR_SET, HdmiCmdDeepColorSet },
261 { HDMI_CMD_DEEP_COLOR_GET, HdmiCmdDeepColorGet },
262 { HDMI_CMD_VIDEO_ATTR_SET, HdmiCmdVideoAttrSet },
263 { HDMI_CMD_AUDIO_ATTR_SET, HdmiCmdAudioAttrSet },
264 { HDMI_CMD_HDR_ATTR_SET, HdmiCmdHdrAttrSet },
265 { HDMI_CMD_READ_SINK_EDID, HdmiCmdReadSinkEdid },
266 { HDMI_CMD_INFOFRAME_SET, HdmiCmdInfoFrameSet },
267 { HDMI_CMD_INFOFRAME_GET, HdmiCmdInfoFrameGet },
268 { HDMI_CMD_REGISTER_HPD_CALLBACK_FUNC, HdmiCmdRegisterHpdCallbackFunc },
269 { HDMI_CMD_UNREGISTER_HPD_CALLBACK_FUNC, HdmiCmdUnregisterHpdCallbackFunc },
270 };
271
272 if (client == NULL || client->device == NULL) {
273 HDF_LOGE("HdmiIoDispatch: client or hdf dev obj is NULL");
274 return HDF_ERR_INVALID_OBJECT;
275 }
276
277 cntlr = (struct HdmiCntlr *)client->device->service;
278 if (cntlr == NULL) {
279 HDF_LOGE("HdmiIoDispatch: service is NULL");
280 return HDF_ERR_INVALID_OBJECT;
281 }
282
283 len = sizeof(dispatchFunc) / sizeof(dispatchFunc[0]);
284 for (i = 0; i < len; i++) {
285 if (dispatchFunc[i].cmd == cmd) {
286 return dispatchFunc[i].func(cntlr, data, reply);
287 }
288 }
289
290 HDF_LOGE("HdmiIoDispatch: cmd %d is not support", cmd);
291 return HDF_ERR_NOT_SUPPORT;
292 }
293