cec-funcs.h 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972
  1. /*
  2. * cec - HDMI Consumer Electronics Control message functions
  3. *
  4. * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
  5. *
  6. * This program is free software; you may redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; version 2 of the License.
  9. *
  10. * Alternatively you can redistribute this file under the terms of the
  11. * BSD license as stated below:
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions
  15. * are met:
  16. * 1. Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. * 2. Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in
  20. * the documentation and/or other materials provided with the
  21. * distribution.
  22. * 3. The names of its contributors may not be used to endorse or promote
  23. * products derived from this software without specific prior written
  24. * permission.
  25. *
  26. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  27. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  28. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  30. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  31. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  32. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  33. * SOFTWARE.
  34. */
  35. /*
  36. * Note: this framework is still in staging and it is likely the API
  37. * will change before it goes out of staging.
  38. *
  39. * Once it is moved out of staging this header will move to uapi.
  40. */
  41. #ifndef _CEC_UAPI_FUNCS_H
  42. #define _CEC_UAPI_FUNCS_H
  43. #include <linux/cec.h>
  44. /* One Touch Play Feature */
  45. static inline void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)
  46. {
  47. msg->len = 4;
  48. msg->msg[0] |= 0xf; /* broadcast */
  49. msg->msg[1] = CEC_MSG_ACTIVE_SOURCE;
  50. msg->msg[2] = phys_addr >> 8;
  51. msg->msg[3] = phys_addr & 0xff;
  52. }
  53. static inline void cec_ops_active_source(const struct cec_msg *msg,
  54. __u16 *phys_addr)
  55. {
  56. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  57. }
  58. static inline void cec_msg_image_view_on(struct cec_msg *msg)
  59. {
  60. msg->len = 2;
  61. msg->msg[1] = CEC_MSG_IMAGE_VIEW_ON;
  62. }
  63. static inline void cec_msg_text_view_on(struct cec_msg *msg)
  64. {
  65. msg->len = 2;
  66. msg->msg[1] = CEC_MSG_TEXT_VIEW_ON;
  67. }
  68. /* Routing Control Feature */
  69. static inline void cec_msg_inactive_source(struct cec_msg *msg,
  70. __u16 phys_addr)
  71. {
  72. msg->len = 4;
  73. msg->msg[1] = CEC_MSG_INACTIVE_SOURCE;
  74. msg->msg[2] = phys_addr >> 8;
  75. msg->msg[3] = phys_addr & 0xff;
  76. }
  77. static inline void cec_ops_inactive_source(const struct cec_msg *msg,
  78. __u16 *phys_addr)
  79. {
  80. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  81. }
  82. static inline void cec_msg_request_active_source(struct cec_msg *msg,
  83. bool reply)
  84. {
  85. msg->len = 2;
  86. msg->msg[0] |= 0xf; /* broadcast */
  87. msg->msg[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE;
  88. msg->reply = reply ? CEC_MSG_ACTIVE_SOURCE : 0;
  89. }
  90. static inline void cec_msg_routing_information(struct cec_msg *msg,
  91. __u16 phys_addr)
  92. {
  93. msg->len = 4;
  94. msg->msg[0] |= 0xf; /* broadcast */
  95. msg->msg[1] = CEC_MSG_ROUTING_INFORMATION;
  96. msg->msg[2] = phys_addr >> 8;
  97. msg->msg[3] = phys_addr & 0xff;
  98. }
  99. static inline void cec_ops_routing_information(const struct cec_msg *msg,
  100. __u16 *phys_addr)
  101. {
  102. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  103. }
  104. static inline void cec_msg_routing_change(struct cec_msg *msg,
  105. bool reply,
  106. __u16 orig_phys_addr,
  107. __u16 new_phys_addr)
  108. {
  109. msg->len = 6;
  110. msg->msg[0] |= 0xf; /* broadcast */
  111. msg->msg[1] = CEC_MSG_ROUTING_CHANGE;
  112. msg->msg[2] = orig_phys_addr >> 8;
  113. msg->msg[3] = orig_phys_addr & 0xff;
  114. msg->msg[4] = new_phys_addr >> 8;
  115. msg->msg[5] = new_phys_addr & 0xff;
  116. msg->reply = reply ? CEC_MSG_ROUTING_INFORMATION : 0;
  117. }
  118. static inline void cec_ops_routing_change(const struct cec_msg *msg,
  119. __u16 *orig_phys_addr,
  120. __u16 *new_phys_addr)
  121. {
  122. *orig_phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  123. *new_phys_addr = (msg->msg[4] << 8) | msg->msg[5];
  124. }
  125. static inline void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)
  126. {
  127. msg->len = 4;
  128. msg->msg[0] |= 0xf; /* broadcast */
  129. msg->msg[1] = CEC_MSG_SET_STREAM_PATH;
  130. msg->msg[2] = phys_addr >> 8;
  131. msg->msg[3] = phys_addr & 0xff;
  132. }
  133. static inline void cec_ops_set_stream_path(const struct cec_msg *msg,
  134. __u16 *phys_addr)
  135. {
  136. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  137. }
  138. /* Standby Feature */
  139. static inline void cec_msg_standby(struct cec_msg *msg)
  140. {
  141. msg->len = 2;
  142. msg->msg[1] = CEC_MSG_STANDBY;
  143. }
  144. /* One Touch Record Feature */
  145. static inline void cec_msg_record_off(struct cec_msg *msg, bool reply)
  146. {
  147. msg->len = 2;
  148. msg->msg[1] = CEC_MSG_RECORD_OFF;
  149. msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
  150. }
  151. struct cec_op_arib_data {
  152. __u16 transport_id;
  153. __u16 service_id;
  154. __u16 orig_network_id;
  155. };
  156. struct cec_op_atsc_data {
  157. __u16 transport_id;
  158. __u16 program_number;
  159. };
  160. struct cec_op_dvb_data {
  161. __u16 transport_id;
  162. __u16 service_id;
  163. __u16 orig_network_id;
  164. };
  165. struct cec_op_channel_data {
  166. __u8 channel_number_fmt;
  167. __u16 major;
  168. __u16 minor;
  169. };
  170. struct cec_op_digital_service_id {
  171. __u8 service_id_method;
  172. __u8 dig_bcast_system;
  173. union {
  174. struct cec_op_arib_data arib;
  175. struct cec_op_atsc_data atsc;
  176. struct cec_op_dvb_data dvb;
  177. struct cec_op_channel_data channel;
  178. };
  179. };
  180. struct cec_op_record_src {
  181. __u8 type;
  182. union {
  183. struct cec_op_digital_service_id digital;
  184. struct {
  185. __u8 ana_bcast_type;
  186. __u16 ana_freq;
  187. __u8 bcast_system;
  188. } analog;
  189. struct {
  190. __u8 plug;
  191. } ext_plug;
  192. struct {
  193. __u16 phys_addr;
  194. } ext_phys_addr;
  195. };
  196. };
  197. static inline void cec_set_digital_service_id(__u8 *msg,
  198. const struct cec_op_digital_service_id *digital)
  199. {
  200. *msg++ = (digital->service_id_method << 7) | digital->dig_bcast_system;
  201. if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
  202. *msg++ = (digital->channel.channel_number_fmt << 2) |
  203. (digital->channel.major >> 8);
  204. *msg++ = digital->channel.major & 0xff;
  205. *msg++ = digital->channel.minor >> 8;
  206. *msg++ = digital->channel.minor & 0xff;
  207. *msg++ = 0;
  208. *msg++ = 0;
  209. return;
  210. }
  211. switch (digital->dig_bcast_system) {
  212. case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN:
  213. case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE:
  214. case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
  215. case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
  216. *msg++ = digital->atsc.transport_id >> 8;
  217. *msg++ = digital->atsc.transport_id & 0xff;
  218. *msg++ = digital->atsc.program_number >> 8;
  219. *msg++ = digital->atsc.program_number & 0xff;
  220. *msg++ = 0;
  221. *msg++ = 0;
  222. break;
  223. default:
  224. *msg++ = digital->dvb.transport_id >> 8;
  225. *msg++ = digital->dvb.transport_id & 0xff;
  226. *msg++ = digital->dvb.service_id >> 8;
  227. *msg++ = digital->dvb.service_id & 0xff;
  228. *msg++ = digital->dvb.orig_network_id >> 8;
  229. *msg++ = digital->dvb.orig_network_id & 0xff;
  230. break;
  231. }
  232. }
  233. static inline void cec_get_digital_service_id(const __u8 *msg,
  234. struct cec_op_digital_service_id *digital)
  235. {
  236. digital->service_id_method = msg[0] >> 7;
  237. digital->dig_bcast_system = msg[0] & 0x7f;
  238. if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
  239. digital->channel.channel_number_fmt = msg[1] >> 2;
  240. digital->channel.major = ((msg[1] & 3) << 6) | msg[2];
  241. digital->channel.minor = (msg[3] << 8) | msg[4];
  242. return;
  243. }
  244. digital->dvb.transport_id = (msg[1] << 8) | msg[2];
  245. digital->dvb.service_id = (msg[3] << 8) | msg[4];
  246. digital->dvb.orig_network_id = (msg[5] << 8) | msg[6];
  247. }
  248. static inline void cec_msg_record_on_own(struct cec_msg *msg)
  249. {
  250. msg->len = 3;
  251. msg->msg[1] = CEC_MSG_RECORD_ON;
  252. msg->msg[2] = CEC_OP_RECORD_SRC_OWN;
  253. }
  254. static inline void cec_msg_record_on_digital(struct cec_msg *msg,
  255. const struct cec_op_digital_service_id *digital)
  256. {
  257. msg->len = 10;
  258. msg->msg[1] = CEC_MSG_RECORD_ON;
  259. msg->msg[2] = CEC_OP_RECORD_SRC_DIGITAL;
  260. cec_set_digital_service_id(msg->msg + 3, digital);
  261. }
  262. static inline void cec_msg_record_on_analog(struct cec_msg *msg,
  263. __u8 ana_bcast_type,
  264. __u16 ana_freq,
  265. __u8 bcast_system)
  266. {
  267. msg->len = 7;
  268. msg->msg[1] = CEC_MSG_RECORD_ON;
  269. msg->msg[2] = CEC_OP_RECORD_SRC_ANALOG;
  270. msg->msg[3] = ana_bcast_type;
  271. msg->msg[4] = ana_freq >> 8;
  272. msg->msg[5] = ana_freq & 0xff;
  273. msg->msg[6] = bcast_system;
  274. }
  275. static inline void cec_msg_record_on_plug(struct cec_msg *msg,
  276. __u8 plug)
  277. {
  278. msg->len = 4;
  279. msg->msg[1] = CEC_MSG_RECORD_ON;
  280. msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PLUG;
  281. msg->msg[3] = plug;
  282. }
  283. static inline void cec_msg_record_on_phys_addr(struct cec_msg *msg,
  284. __u16 phys_addr)
  285. {
  286. msg->len = 5;
  287. msg->msg[1] = CEC_MSG_RECORD_ON;
  288. msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR;
  289. msg->msg[3] = phys_addr >> 8;
  290. msg->msg[4] = phys_addr & 0xff;
  291. }
  292. static inline void cec_msg_record_on(struct cec_msg *msg,
  293. bool reply,
  294. const struct cec_op_record_src *rec_src)
  295. {
  296. switch (rec_src->type) {
  297. case CEC_OP_RECORD_SRC_OWN:
  298. cec_msg_record_on_own(msg);
  299. break;
  300. case CEC_OP_RECORD_SRC_DIGITAL:
  301. cec_msg_record_on_digital(msg, &rec_src->digital);
  302. break;
  303. case CEC_OP_RECORD_SRC_ANALOG:
  304. cec_msg_record_on_analog(msg,
  305. rec_src->analog.ana_bcast_type,
  306. rec_src->analog.ana_freq,
  307. rec_src->analog.bcast_system);
  308. break;
  309. case CEC_OP_RECORD_SRC_EXT_PLUG:
  310. cec_msg_record_on_plug(msg, rec_src->ext_plug.plug);
  311. break;
  312. case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
  313. cec_msg_record_on_phys_addr(msg,
  314. rec_src->ext_phys_addr.phys_addr);
  315. break;
  316. }
  317. msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
  318. }
  319. static inline void cec_ops_record_on(const struct cec_msg *msg,
  320. struct cec_op_record_src *rec_src)
  321. {
  322. rec_src->type = msg->msg[2];
  323. switch (rec_src->type) {
  324. case CEC_OP_RECORD_SRC_OWN:
  325. break;
  326. case CEC_OP_RECORD_SRC_DIGITAL:
  327. cec_get_digital_service_id(msg->msg + 3, &rec_src->digital);
  328. break;
  329. case CEC_OP_RECORD_SRC_ANALOG:
  330. rec_src->analog.ana_bcast_type = msg->msg[3];
  331. rec_src->analog.ana_freq =
  332. (msg->msg[4] << 8) | msg->msg[5];
  333. rec_src->analog.bcast_system = msg->msg[6];
  334. break;
  335. case CEC_OP_RECORD_SRC_EXT_PLUG:
  336. rec_src->ext_plug.plug = msg->msg[3];
  337. break;
  338. case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
  339. rec_src->ext_phys_addr.phys_addr =
  340. (msg->msg[3] << 8) | msg->msg[4];
  341. break;
  342. }
  343. }
  344. static inline void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status)
  345. {
  346. msg->len = 3;
  347. msg->msg[1] = CEC_MSG_RECORD_STATUS;
  348. msg->msg[2] = rec_status;
  349. }
  350. static inline void cec_ops_record_status(const struct cec_msg *msg,
  351. __u8 *rec_status)
  352. {
  353. *rec_status = msg->msg[2];
  354. }
  355. static inline void cec_msg_record_tv_screen(struct cec_msg *msg,
  356. bool reply)
  357. {
  358. msg->len = 2;
  359. msg->msg[1] = CEC_MSG_RECORD_TV_SCREEN;
  360. msg->reply = reply ? CEC_MSG_RECORD_ON : 0;
  361. }
  362. /* Timer Programming Feature */
  363. static inline void cec_msg_timer_status(struct cec_msg *msg,
  364. __u8 timer_overlap_warning,
  365. __u8 media_info,
  366. __u8 prog_info,
  367. __u8 prog_error,
  368. __u8 duration_hr,
  369. __u8 duration_min)
  370. {
  371. msg->len = 3;
  372. msg->msg[1] = CEC_MSG_TIMER_STATUS;
  373. msg->msg[2] = (timer_overlap_warning << 7) |
  374. (media_info << 5) |
  375. (prog_info ? 0x10 : 0) |
  376. (prog_info ? prog_info : prog_error);
  377. if (prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
  378. prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
  379. prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
  380. msg->len += 2;
  381. msg->msg[3] = ((duration_hr / 10) << 4) | (duration_hr % 10);
  382. msg->msg[4] = ((duration_min / 10) << 4) | (duration_min % 10);
  383. }
  384. }
  385. static inline void cec_ops_timer_status(const struct cec_msg *msg,
  386. __u8 *timer_overlap_warning,
  387. __u8 *media_info,
  388. __u8 *prog_info,
  389. __u8 *prog_error,
  390. __u8 *duration_hr,
  391. __u8 *duration_min)
  392. {
  393. *timer_overlap_warning = msg->msg[2] >> 7;
  394. *media_info = (msg->msg[2] >> 5) & 3;
  395. if (msg->msg[2] & 0x10) {
  396. *prog_info = msg->msg[2] & 0xf;
  397. *prog_error = 0;
  398. } else {
  399. *prog_info = 0;
  400. *prog_error = msg->msg[2] & 0xf;
  401. }
  402. if (*prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
  403. *prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
  404. *prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
  405. *duration_hr = (msg->msg[3] >> 4) * 10 + (msg->msg[3] & 0xf);
  406. *duration_min = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
  407. } else {
  408. *duration_hr = *duration_min = 0;
  409. }
  410. }
  411. static inline void cec_msg_timer_cleared_status(struct cec_msg *msg,
  412. __u8 timer_cleared_status)
  413. {
  414. msg->len = 3;
  415. msg->msg[1] = CEC_MSG_TIMER_CLEARED_STATUS;
  416. msg->msg[2] = timer_cleared_status;
  417. }
  418. static inline void cec_ops_timer_cleared_status(const struct cec_msg *msg,
  419. __u8 *timer_cleared_status)
  420. {
  421. *timer_cleared_status = msg->msg[2];
  422. }
  423. static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg,
  424. bool reply,
  425. __u8 day,
  426. __u8 month,
  427. __u8 start_hr,
  428. __u8 start_min,
  429. __u8 duration_hr,
  430. __u8 duration_min,
  431. __u8 recording_seq,
  432. __u8 ana_bcast_type,
  433. __u16 ana_freq,
  434. __u8 bcast_system)
  435. {
  436. msg->len = 13;
  437. msg->msg[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER;
  438. msg->msg[2] = day;
  439. msg->msg[3] = month;
  440. /* Hours and minutes are in BCD format */
  441. msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
  442. msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
  443. msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
  444. msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
  445. msg->msg[8] = recording_seq;
  446. msg->msg[9] = ana_bcast_type;
  447. msg->msg[10] = ana_freq >> 8;
  448. msg->msg[11] = ana_freq & 0xff;
  449. msg->msg[12] = bcast_system;
  450. msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
  451. }
  452. static inline void cec_ops_clear_analogue_timer(const struct cec_msg *msg,
  453. __u8 *day,
  454. __u8 *month,
  455. __u8 *start_hr,
  456. __u8 *start_min,
  457. __u8 *duration_hr,
  458. __u8 *duration_min,
  459. __u8 *recording_seq,
  460. __u8 *ana_bcast_type,
  461. __u16 *ana_freq,
  462. __u8 *bcast_system)
  463. {
  464. *day = msg->msg[2];
  465. *month = msg->msg[3];
  466. /* Hours and minutes are in BCD format */
  467. *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
  468. *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
  469. *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
  470. *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
  471. *recording_seq = msg->msg[8];
  472. *ana_bcast_type = msg->msg[9];
  473. *ana_freq = (msg->msg[10] << 8) | msg->msg[11];
  474. *bcast_system = msg->msg[12];
  475. }
  476. static inline void cec_msg_clear_digital_timer(struct cec_msg *msg,
  477. bool reply,
  478. __u8 day,
  479. __u8 month,
  480. __u8 start_hr,
  481. __u8 start_min,
  482. __u8 duration_hr,
  483. __u8 duration_min,
  484. __u8 recording_seq,
  485. const struct cec_op_digital_service_id *digital)
  486. {
  487. msg->len = 16;
  488. msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
  489. msg->msg[1] = CEC_MSG_CLEAR_DIGITAL_TIMER;
  490. msg->msg[2] = day;
  491. msg->msg[3] = month;
  492. /* Hours and minutes are in BCD format */
  493. msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
  494. msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
  495. msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
  496. msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
  497. msg->msg[8] = recording_seq;
  498. cec_set_digital_service_id(msg->msg + 9, digital);
  499. }
  500. static inline void cec_ops_clear_digital_timer(const struct cec_msg *msg,
  501. __u8 *day,
  502. __u8 *month,
  503. __u8 *start_hr,
  504. __u8 *start_min,
  505. __u8 *duration_hr,
  506. __u8 *duration_min,
  507. __u8 *recording_seq,
  508. struct cec_op_digital_service_id *digital)
  509. {
  510. *day = msg->msg[2];
  511. *month = msg->msg[3];
  512. /* Hours and minutes are in BCD format */
  513. *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
  514. *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
  515. *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
  516. *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
  517. *recording_seq = msg->msg[8];
  518. cec_get_digital_service_id(msg->msg + 9, digital);
  519. }
  520. static inline void cec_msg_clear_ext_timer(struct cec_msg *msg,
  521. bool reply,
  522. __u8 day,
  523. __u8 month,
  524. __u8 start_hr,
  525. __u8 start_min,
  526. __u8 duration_hr,
  527. __u8 duration_min,
  528. __u8 recording_seq,
  529. __u8 ext_src_spec,
  530. __u8 plug,
  531. __u16 phys_addr)
  532. {
  533. msg->len = 13;
  534. msg->msg[1] = CEC_MSG_CLEAR_EXT_TIMER;
  535. msg->msg[2] = day;
  536. msg->msg[3] = month;
  537. /* Hours and minutes are in BCD format */
  538. msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
  539. msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
  540. msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
  541. msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
  542. msg->msg[8] = recording_seq;
  543. msg->msg[9] = ext_src_spec;
  544. msg->msg[10] = plug;
  545. msg->msg[11] = phys_addr >> 8;
  546. msg->msg[12] = phys_addr & 0xff;
  547. msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
  548. }
  549. static inline void cec_ops_clear_ext_timer(const struct cec_msg *msg,
  550. __u8 *day,
  551. __u8 *month,
  552. __u8 *start_hr,
  553. __u8 *start_min,
  554. __u8 *duration_hr,
  555. __u8 *duration_min,
  556. __u8 *recording_seq,
  557. __u8 *ext_src_spec,
  558. __u8 *plug,
  559. __u16 *phys_addr)
  560. {
  561. *day = msg->msg[2];
  562. *month = msg->msg[3];
  563. /* Hours and minutes are in BCD format */
  564. *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
  565. *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
  566. *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
  567. *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
  568. *recording_seq = msg->msg[8];
  569. *ext_src_spec = msg->msg[9];
  570. *plug = msg->msg[10];
  571. *phys_addr = (msg->msg[11] << 8) | msg->msg[12];
  572. }
  573. static inline void cec_msg_set_analogue_timer(struct cec_msg *msg,
  574. bool reply,
  575. __u8 day,
  576. __u8 month,
  577. __u8 start_hr,
  578. __u8 start_min,
  579. __u8 duration_hr,
  580. __u8 duration_min,
  581. __u8 recording_seq,
  582. __u8 ana_bcast_type,
  583. __u16 ana_freq,
  584. __u8 bcast_system)
  585. {
  586. msg->len = 13;
  587. msg->msg[1] = CEC_MSG_SET_ANALOGUE_TIMER;
  588. msg->msg[2] = day;
  589. msg->msg[3] = month;
  590. /* Hours and minutes are in BCD format */
  591. msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
  592. msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
  593. msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
  594. msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
  595. msg->msg[8] = recording_seq;
  596. msg->msg[9] = ana_bcast_type;
  597. msg->msg[10] = ana_freq >> 8;
  598. msg->msg[11] = ana_freq & 0xff;
  599. msg->msg[12] = bcast_system;
  600. msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
  601. }
  602. static inline void cec_ops_set_analogue_timer(const struct cec_msg *msg,
  603. __u8 *day,
  604. __u8 *month,
  605. __u8 *start_hr,
  606. __u8 *start_min,
  607. __u8 *duration_hr,
  608. __u8 *duration_min,
  609. __u8 *recording_seq,
  610. __u8 *ana_bcast_type,
  611. __u16 *ana_freq,
  612. __u8 *bcast_system)
  613. {
  614. *day = msg->msg[2];
  615. *month = msg->msg[3];
  616. /* Hours and minutes are in BCD format */
  617. *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
  618. *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
  619. *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
  620. *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
  621. *recording_seq = msg->msg[8];
  622. *ana_bcast_type = msg->msg[9];
  623. *ana_freq = (msg->msg[10] << 8) | msg->msg[11];
  624. *bcast_system = msg->msg[12];
  625. }
  626. static inline void cec_msg_set_digital_timer(struct cec_msg *msg,
  627. bool reply,
  628. __u8 day,
  629. __u8 month,
  630. __u8 start_hr,
  631. __u8 start_min,
  632. __u8 duration_hr,
  633. __u8 duration_min,
  634. __u8 recording_seq,
  635. const struct cec_op_digital_service_id *digital)
  636. {
  637. msg->len = 16;
  638. msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
  639. msg->msg[1] = CEC_MSG_SET_DIGITAL_TIMER;
  640. msg->msg[2] = day;
  641. msg->msg[3] = month;
  642. /* Hours and minutes are in BCD format */
  643. msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
  644. msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
  645. msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
  646. msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
  647. msg->msg[8] = recording_seq;
  648. cec_set_digital_service_id(msg->msg + 9, digital);
  649. }
  650. static inline void cec_ops_set_digital_timer(const struct cec_msg *msg,
  651. __u8 *day,
  652. __u8 *month,
  653. __u8 *start_hr,
  654. __u8 *start_min,
  655. __u8 *duration_hr,
  656. __u8 *duration_min,
  657. __u8 *recording_seq,
  658. struct cec_op_digital_service_id *digital)
  659. {
  660. *day = msg->msg[2];
  661. *month = msg->msg[3];
  662. /* Hours and minutes are in BCD format */
  663. *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
  664. *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
  665. *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
  666. *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
  667. *recording_seq = msg->msg[8];
  668. cec_get_digital_service_id(msg->msg + 9, digital);
  669. }
  670. static inline void cec_msg_set_ext_timer(struct cec_msg *msg,
  671. bool reply,
  672. __u8 day,
  673. __u8 month,
  674. __u8 start_hr,
  675. __u8 start_min,
  676. __u8 duration_hr,
  677. __u8 duration_min,
  678. __u8 recording_seq,
  679. __u8 ext_src_spec,
  680. __u8 plug,
  681. __u16 phys_addr)
  682. {
  683. msg->len = 13;
  684. msg->msg[1] = CEC_MSG_SET_EXT_TIMER;
  685. msg->msg[2] = day;
  686. msg->msg[3] = month;
  687. /* Hours and minutes are in BCD format */
  688. msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
  689. msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
  690. msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
  691. msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
  692. msg->msg[8] = recording_seq;
  693. msg->msg[9] = ext_src_spec;
  694. msg->msg[10] = plug;
  695. msg->msg[11] = phys_addr >> 8;
  696. msg->msg[12] = phys_addr & 0xff;
  697. msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
  698. }
  699. static inline void cec_ops_set_ext_timer(const struct cec_msg *msg,
  700. __u8 *day,
  701. __u8 *month,
  702. __u8 *start_hr,
  703. __u8 *start_min,
  704. __u8 *duration_hr,
  705. __u8 *duration_min,
  706. __u8 *recording_seq,
  707. __u8 *ext_src_spec,
  708. __u8 *plug,
  709. __u16 *phys_addr)
  710. {
  711. *day = msg->msg[2];
  712. *month = msg->msg[3];
  713. /* Hours and minutes are in BCD format */
  714. *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
  715. *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
  716. *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
  717. *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
  718. *recording_seq = msg->msg[8];
  719. *ext_src_spec = msg->msg[9];
  720. *plug = msg->msg[10];
  721. *phys_addr = (msg->msg[11] << 8) | msg->msg[12];
  722. }
  723. static inline void cec_msg_set_timer_program_title(struct cec_msg *msg,
  724. const char *prog_title)
  725. {
  726. unsigned int len = strlen(prog_title);
  727. if (len > 14)
  728. len = 14;
  729. msg->len = 2 + len;
  730. msg->msg[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE;
  731. memcpy(msg->msg + 2, prog_title, len);
  732. }
  733. static inline void cec_ops_set_timer_program_title(const struct cec_msg *msg,
  734. char *prog_title)
  735. {
  736. unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
  737. if (len > 14)
  738. len = 14;
  739. memcpy(prog_title, msg->msg + 2, len);
  740. prog_title[len] = '\0';
  741. }
  742. /* System Information Feature */
  743. static inline void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version)
  744. {
  745. msg->len = 3;
  746. msg->msg[1] = CEC_MSG_CEC_VERSION;
  747. msg->msg[2] = cec_version;
  748. }
  749. static inline void cec_ops_cec_version(const struct cec_msg *msg,
  750. __u8 *cec_version)
  751. {
  752. *cec_version = msg->msg[2];
  753. }
  754. static inline void cec_msg_get_cec_version(struct cec_msg *msg,
  755. bool reply)
  756. {
  757. msg->len = 2;
  758. msg->msg[1] = CEC_MSG_GET_CEC_VERSION;
  759. msg->reply = reply ? CEC_MSG_CEC_VERSION : 0;
  760. }
  761. static inline void cec_msg_report_physical_addr(struct cec_msg *msg,
  762. __u16 phys_addr, __u8 prim_devtype)
  763. {
  764. msg->len = 5;
  765. msg->msg[0] |= 0xf; /* broadcast */
  766. msg->msg[1] = CEC_MSG_REPORT_PHYSICAL_ADDR;
  767. msg->msg[2] = phys_addr >> 8;
  768. msg->msg[3] = phys_addr & 0xff;
  769. msg->msg[4] = prim_devtype;
  770. }
  771. static inline void cec_ops_report_physical_addr(const struct cec_msg *msg,
  772. __u16 *phys_addr, __u8 *prim_devtype)
  773. {
  774. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  775. *prim_devtype = msg->msg[4];
  776. }
  777. static inline void cec_msg_give_physical_addr(struct cec_msg *msg,
  778. bool reply)
  779. {
  780. msg->len = 2;
  781. msg->msg[1] = CEC_MSG_GIVE_PHYSICAL_ADDR;
  782. msg->reply = reply ? CEC_MSG_REPORT_PHYSICAL_ADDR : 0;
  783. }
  784. static inline void cec_msg_set_menu_language(struct cec_msg *msg,
  785. const char *language)
  786. {
  787. msg->len = 5;
  788. msg->msg[0] |= 0xf; /* broadcast */
  789. msg->msg[1] = CEC_MSG_SET_MENU_LANGUAGE;
  790. memcpy(msg->msg + 2, language, 3);
  791. }
  792. static inline void cec_ops_set_menu_language(const struct cec_msg *msg,
  793. char *language)
  794. {
  795. memcpy(language, msg->msg + 2, 3);
  796. language[3] = '\0';
  797. }
  798. static inline void cec_msg_get_menu_language(struct cec_msg *msg,
  799. bool reply)
  800. {
  801. msg->len = 2;
  802. msg->msg[1] = CEC_MSG_GET_MENU_LANGUAGE;
  803. msg->reply = reply ? CEC_MSG_SET_MENU_LANGUAGE : 0;
  804. }
  805. /*
  806. * Assumes a single RC Profile byte and a single Device Features byte,
  807. * i.e. no extended features are supported by this helper function.
  808. *
  809. * As of CEC 2.0 no extended features are defined, should those be added
  810. * in the future, then this function needs to be adapted or a new function
  811. * should be added.
  812. */
  813. static inline void cec_msg_report_features(struct cec_msg *msg,
  814. __u8 cec_version, __u8 all_device_types,
  815. __u8 rc_profile, __u8 dev_features)
  816. {
  817. msg->len = 6;
  818. msg->msg[0] |= 0xf; /* broadcast */
  819. msg->msg[1] = CEC_MSG_REPORT_FEATURES;
  820. msg->msg[2] = cec_version;
  821. msg->msg[3] = all_device_types;
  822. msg->msg[4] = rc_profile;
  823. msg->msg[5] = dev_features;
  824. }
  825. static inline void cec_ops_report_features(const struct cec_msg *msg,
  826. __u8 *cec_version, __u8 *all_device_types,
  827. const __u8 **rc_profile, const __u8 **dev_features)
  828. {
  829. const __u8 *p = &msg->msg[4];
  830. *cec_version = msg->msg[2];
  831. *all_device_types = msg->msg[3];
  832. *rc_profile = p;
  833. while (p < &msg->msg[14] && (*p & CEC_OP_FEAT_EXT))
  834. p++;
  835. if (!(*p & CEC_OP_FEAT_EXT)) {
  836. *dev_features = p + 1;
  837. while (p < &msg->msg[15] && (*p & CEC_OP_FEAT_EXT))
  838. p++;
  839. }
  840. if (*p & CEC_OP_FEAT_EXT)
  841. *rc_profile = *dev_features = NULL;
  842. }
  843. static inline void cec_msg_give_features(struct cec_msg *msg,
  844. bool reply)
  845. {
  846. msg->len = 2;
  847. msg->msg[1] = CEC_MSG_GIVE_FEATURES;
  848. msg->reply = reply ? CEC_MSG_REPORT_FEATURES : 0;
  849. }
  850. /* Deck Control Feature */
  851. static inline void cec_msg_deck_control(struct cec_msg *msg,
  852. __u8 deck_control_mode)
  853. {
  854. msg->len = 3;
  855. msg->msg[1] = CEC_MSG_DECK_CONTROL;
  856. msg->msg[2] = deck_control_mode;
  857. }
  858. static inline void cec_ops_deck_control(const struct cec_msg *msg,
  859. __u8 *deck_control_mode)
  860. {
  861. *deck_control_mode = msg->msg[2];
  862. }
  863. static inline void cec_msg_deck_status(struct cec_msg *msg,
  864. __u8 deck_info)
  865. {
  866. msg->len = 3;
  867. msg->msg[1] = CEC_MSG_DECK_STATUS;
  868. msg->msg[2] = deck_info;
  869. }
  870. static inline void cec_ops_deck_status(const struct cec_msg *msg,
  871. __u8 *deck_info)
  872. {
  873. *deck_info = msg->msg[2];
  874. }
  875. static inline void cec_msg_give_deck_status(struct cec_msg *msg,
  876. bool reply,
  877. __u8 status_req)
  878. {
  879. msg->len = 3;
  880. msg->msg[1] = CEC_MSG_GIVE_DECK_STATUS;
  881. msg->msg[2] = status_req;
  882. msg->reply = reply ? CEC_MSG_DECK_STATUS : 0;
  883. }
  884. static inline void cec_ops_give_deck_status(const struct cec_msg *msg,
  885. __u8 *status_req)
  886. {
  887. *status_req = msg->msg[2];
  888. }
  889. static inline void cec_msg_play(struct cec_msg *msg,
  890. __u8 play_mode)
  891. {
  892. msg->len = 3;
  893. msg->msg[1] = CEC_MSG_PLAY;
  894. msg->msg[2] = play_mode;
  895. }
  896. static inline void cec_ops_play(const struct cec_msg *msg,
  897. __u8 *play_mode)
  898. {
  899. *play_mode = msg->msg[2];
  900. }
  901. /* Tuner Control Feature */
  902. struct cec_op_tuner_device_info {
  903. __u8 rec_flag;
  904. __u8 tuner_display_info;
  905. bool is_analog;
  906. union {
  907. struct cec_op_digital_service_id digital;
  908. struct {
  909. __u8 ana_bcast_type;
  910. __u16 ana_freq;
  911. __u8 bcast_system;
  912. } analog;
  913. };
  914. };
  915. static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
  916. __u8 rec_flag,
  917. __u8 tuner_display_info,
  918. __u8 ana_bcast_type,
  919. __u16 ana_freq,
  920. __u8 bcast_system)
  921. {
  922. msg->len = 7;
  923. msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
  924. msg->msg[2] = (rec_flag << 7) | tuner_display_info;
  925. msg->msg[3] = ana_bcast_type;
  926. msg->msg[4] = ana_freq >> 8;
  927. msg->msg[5] = ana_freq & 0xff;
  928. msg->msg[6] = bcast_system;
  929. }
  930. static inline void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
  931. __u8 rec_flag, __u8 tuner_display_info,
  932. const struct cec_op_digital_service_id *digital)
  933. {
  934. msg->len = 10;
  935. msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
  936. msg->msg[2] = (rec_flag << 7) | tuner_display_info;
  937. cec_set_digital_service_id(msg->msg + 3, digital);
  938. }
  939. static inline void cec_msg_tuner_device_status(struct cec_msg *msg,
  940. const struct cec_op_tuner_device_info *tuner_dev_info)
  941. {
  942. if (tuner_dev_info->is_analog)
  943. cec_msg_tuner_device_status_analog(msg,
  944. tuner_dev_info->rec_flag,
  945. tuner_dev_info->tuner_display_info,
  946. tuner_dev_info->analog.ana_bcast_type,
  947. tuner_dev_info->analog.ana_freq,
  948. tuner_dev_info->analog.bcast_system);
  949. else
  950. cec_msg_tuner_device_status_digital(msg,
  951. tuner_dev_info->rec_flag,
  952. tuner_dev_info->tuner_display_info,
  953. &tuner_dev_info->digital);
  954. }
  955. static inline void cec_ops_tuner_device_status(const struct cec_msg *msg,
  956. struct cec_op_tuner_device_info *tuner_dev_info)
  957. {
  958. tuner_dev_info->is_analog = msg->len < 10;
  959. tuner_dev_info->rec_flag = msg->msg[2] >> 7;
  960. tuner_dev_info->tuner_display_info = msg->msg[2] & 0x7f;
  961. if (tuner_dev_info->is_analog) {
  962. tuner_dev_info->analog.ana_bcast_type = msg->msg[3];
  963. tuner_dev_info->analog.ana_freq = (msg->msg[4] << 8) | msg->msg[5];
  964. tuner_dev_info->analog.bcast_system = msg->msg[6];
  965. return;
  966. }
  967. cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);
  968. }
  969. static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,
  970. bool reply,
  971. __u8 status_req)
  972. {
  973. msg->len = 3;
  974. msg->msg[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS;
  975. msg->msg[2] = status_req;
  976. msg->reply = reply ? CEC_MSG_TUNER_DEVICE_STATUS : 0;
  977. }
  978. static inline void cec_ops_give_tuner_device_status(const struct cec_msg *msg,
  979. __u8 *status_req)
  980. {
  981. *status_req = msg->msg[2];
  982. }
  983. static inline void cec_msg_select_analogue_service(struct cec_msg *msg,
  984. __u8 ana_bcast_type,
  985. __u16 ana_freq,
  986. __u8 bcast_system)
  987. {
  988. msg->len = 6;
  989. msg->msg[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE;
  990. msg->msg[2] = ana_bcast_type;
  991. msg->msg[3] = ana_freq >> 8;
  992. msg->msg[4] = ana_freq & 0xff;
  993. msg->msg[5] = bcast_system;
  994. }
  995. static inline void cec_ops_select_analogue_service(const struct cec_msg *msg,
  996. __u8 *ana_bcast_type,
  997. __u16 *ana_freq,
  998. __u8 *bcast_system)
  999. {
  1000. *ana_bcast_type = msg->msg[2];
  1001. *ana_freq = (msg->msg[3] << 8) | msg->msg[4];
  1002. *bcast_system = msg->msg[5];
  1003. }
  1004. static inline void cec_msg_select_digital_service(struct cec_msg *msg,
  1005. const struct cec_op_digital_service_id *digital)
  1006. {
  1007. msg->len = 9;
  1008. msg->msg[1] = CEC_MSG_SELECT_DIGITAL_SERVICE;
  1009. cec_set_digital_service_id(msg->msg + 2, digital);
  1010. }
  1011. static inline void cec_ops_select_digital_service(const struct cec_msg *msg,
  1012. struct cec_op_digital_service_id *digital)
  1013. {
  1014. cec_get_digital_service_id(msg->msg + 2, digital);
  1015. }
  1016. static inline void cec_msg_tuner_step_decrement(struct cec_msg *msg)
  1017. {
  1018. msg->len = 2;
  1019. msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;
  1020. }
  1021. static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)
  1022. {
  1023. msg->len = 2;
  1024. msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;
  1025. }
  1026. /* Vendor Specific Commands Feature */
  1027. static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
  1028. {
  1029. msg->len = 5;
  1030. msg->msg[0] |= 0xf; /* broadcast */
  1031. msg->msg[1] = CEC_MSG_DEVICE_VENDOR_ID;
  1032. msg->msg[2] = vendor_id >> 16;
  1033. msg->msg[3] = (vendor_id >> 8) & 0xff;
  1034. msg->msg[4] = vendor_id & 0xff;
  1035. }
  1036. static inline void cec_ops_device_vendor_id(const struct cec_msg *msg,
  1037. __u32 *vendor_id)
  1038. {
  1039. *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
  1040. }
  1041. static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,
  1042. bool reply)
  1043. {
  1044. msg->len = 2;
  1045. msg->msg[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID;
  1046. msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;
  1047. }
  1048. static inline void cec_msg_vendor_command(struct cec_msg *msg,
  1049. __u8 size, const __u8 *vendor_cmd)
  1050. {
  1051. if (size > 14)
  1052. size = 14;
  1053. msg->len = 2 + size;
  1054. msg->msg[1] = CEC_MSG_VENDOR_COMMAND;
  1055. memcpy(msg->msg + 2, vendor_cmd, size);
  1056. }
  1057. static inline void cec_ops_vendor_command(const struct cec_msg *msg,
  1058. __u8 *size,
  1059. const __u8 **vendor_cmd)
  1060. {
  1061. *size = msg->len - 2;
  1062. if (*size > 14)
  1063. *size = 14;
  1064. *vendor_cmd = msg->msg + 2;
  1065. }
  1066. static inline void cec_msg_vendor_command_with_id(struct cec_msg *msg,
  1067. __u32 vendor_id, __u8 size,
  1068. const __u8 *vendor_cmd)
  1069. {
  1070. if (size > 11)
  1071. size = 11;
  1072. msg->len = 5 + size;
  1073. msg->msg[1] = CEC_MSG_VENDOR_COMMAND_WITH_ID;
  1074. msg->msg[2] = vendor_id >> 16;
  1075. msg->msg[3] = (vendor_id >> 8) & 0xff;
  1076. msg->msg[4] = vendor_id & 0xff;
  1077. memcpy(msg->msg + 5, vendor_cmd, size);
  1078. }
  1079. static inline void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
  1080. __u32 *vendor_id, __u8 *size,
  1081. const __u8 **vendor_cmd)
  1082. {
  1083. *size = msg->len - 5;
  1084. if (*size > 11)
  1085. *size = 11;
  1086. *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
  1087. *vendor_cmd = msg->msg + 5;
  1088. }
  1089. static inline void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
  1090. __u8 size,
  1091. const __u8 *rc_code)
  1092. {
  1093. if (size > 14)
  1094. size = 14;
  1095. msg->len = 2 + size;
  1096. msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN;
  1097. memcpy(msg->msg + 2, rc_code, size);
  1098. }
  1099. static inline void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
  1100. __u8 *size,
  1101. const __u8 **rc_code)
  1102. {
  1103. *size = msg->len - 2;
  1104. if (*size > 14)
  1105. *size = 14;
  1106. *rc_code = msg->msg + 2;
  1107. }
  1108. static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
  1109. {
  1110. msg->len = 2;
  1111. msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;
  1112. }
  1113. /* OSD Display Feature */
  1114. static inline void cec_msg_set_osd_string(struct cec_msg *msg,
  1115. __u8 disp_ctl,
  1116. const char *osd)
  1117. {
  1118. unsigned int len = strlen(osd);
  1119. if (len > 13)
  1120. len = 13;
  1121. msg->len = 3 + len;
  1122. msg->msg[1] = CEC_MSG_SET_OSD_STRING;
  1123. msg->msg[2] = disp_ctl;
  1124. memcpy(msg->msg + 3, osd, len);
  1125. }
  1126. static inline void cec_ops_set_osd_string(const struct cec_msg *msg,
  1127. __u8 *disp_ctl,
  1128. char *osd)
  1129. {
  1130. unsigned int len = msg->len > 3 ? msg->len - 3 : 0;
  1131. *disp_ctl = msg->msg[2];
  1132. if (len > 13)
  1133. len = 13;
  1134. memcpy(osd, msg->msg + 3, len);
  1135. osd[len] = '\0';
  1136. }
  1137. /* Device OSD Transfer Feature */
  1138. static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
  1139. {
  1140. unsigned int len = strlen(name);
  1141. if (len > 14)
  1142. len = 14;
  1143. msg->len = 2 + len;
  1144. msg->msg[1] = CEC_MSG_SET_OSD_NAME;
  1145. memcpy(msg->msg + 2, name, len);
  1146. }
  1147. static inline void cec_ops_set_osd_name(const struct cec_msg *msg,
  1148. char *name)
  1149. {
  1150. unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
  1151. if (len > 14)
  1152. len = 14;
  1153. memcpy(name, msg->msg + 2, len);
  1154. name[len] = '\0';
  1155. }
  1156. static inline void cec_msg_give_osd_name(struct cec_msg *msg,
  1157. bool reply)
  1158. {
  1159. msg->len = 2;
  1160. msg->msg[1] = CEC_MSG_GIVE_OSD_NAME;
  1161. msg->reply = reply ? CEC_MSG_SET_OSD_NAME : 0;
  1162. }
  1163. /* Device Menu Control Feature */
  1164. static inline void cec_msg_menu_status(struct cec_msg *msg,
  1165. __u8 menu_state)
  1166. {
  1167. msg->len = 3;
  1168. msg->msg[1] = CEC_MSG_MENU_STATUS;
  1169. msg->msg[2] = menu_state;
  1170. }
  1171. static inline void cec_ops_menu_status(const struct cec_msg *msg,
  1172. __u8 *menu_state)
  1173. {
  1174. *menu_state = msg->msg[2];
  1175. }
  1176. static inline void cec_msg_menu_request(struct cec_msg *msg,
  1177. bool reply,
  1178. __u8 menu_req)
  1179. {
  1180. msg->len = 3;
  1181. msg->msg[1] = CEC_MSG_MENU_REQUEST;
  1182. msg->msg[2] = menu_req;
  1183. msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;
  1184. }
  1185. static inline void cec_ops_menu_request(const struct cec_msg *msg,
  1186. __u8 *menu_req)
  1187. {
  1188. *menu_req = msg->msg[2];
  1189. }
  1190. struct cec_op_ui_command {
  1191. __u8 ui_cmd;
  1192. bool has_opt_arg;
  1193. union {
  1194. struct cec_op_channel_data channel_identifier;
  1195. __u8 ui_broadcast_type;
  1196. __u8 ui_sound_presentation_control;
  1197. __u8 play_mode;
  1198. __u8 ui_function_media;
  1199. __u8 ui_function_select_av_input;
  1200. __u8 ui_function_select_audio_input;
  1201. };
  1202. };
  1203. static inline void cec_msg_user_control_pressed(struct cec_msg *msg,
  1204. const struct cec_op_ui_command *ui_cmd)
  1205. {
  1206. msg->len = 3;
  1207. msg->msg[1] = CEC_MSG_USER_CONTROL_PRESSED;
  1208. msg->msg[2] = ui_cmd->ui_cmd;
  1209. if (!ui_cmd->has_opt_arg)
  1210. return;
  1211. switch (ui_cmd->ui_cmd) {
  1212. case 0x56:
  1213. case 0x57:
  1214. case 0x60:
  1215. case 0x68:
  1216. case 0x69:
  1217. case 0x6a:
  1218. /* The optional operand is one byte for all these ui commands */
  1219. msg->len++;
  1220. msg->msg[3] = ui_cmd->play_mode;
  1221. break;
  1222. case 0x67:
  1223. msg->len += 4;
  1224. msg->msg[3] = (ui_cmd->channel_identifier.channel_number_fmt << 2) |
  1225. (ui_cmd->channel_identifier.major >> 8);
  1226. msg->msg[4] = ui_cmd->channel_identifier.major & 0xff;
  1227. msg->msg[5] = ui_cmd->channel_identifier.minor >> 8;
  1228. msg->msg[6] = ui_cmd->channel_identifier.minor & 0xff;
  1229. break;
  1230. }
  1231. }
  1232. static inline void cec_ops_user_control_pressed(const struct cec_msg *msg,
  1233. struct cec_op_ui_command *ui_cmd)
  1234. {
  1235. ui_cmd->ui_cmd = msg->msg[2];
  1236. ui_cmd->has_opt_arg = false;
  1237. if (msg->len == 3)
  1238. return;
  1239. switch (ui_cmd->ui_cmd) {
  1240. case 0x56:
  1241. case 0x57:
  1242. case 0x60:
  1243. case 0x68:
  1244. case 0x69:
  1245. case 0x6a:
  1246. /* The optional operand is one byte for all these ui commands */
  1247. ui_cmd->play_mode = msg->msg[3];
  1248. ui_cmd->has_opt_arg = true;
  1249. break;
  1250. case 0x67:
  1251. if (msg->len < 7)
  1252. break;
  1253. ui_cmd->has_opt_arg = true;
  1254. ui_cmd->channel_identifier.channel_number_fmt = msg->msg[3] >> 2;
  1255. ui_cmd->channel_identifier.major = ((msg->msg[3] & 3) << 6) | msg->msg[4];
  1256. ui_cmd->channel_identifier.minor = (msg->msg[5] << 8) | msg->msg[6];
  1257. break;
  1258. }
  1259. }
  1260. static inline void cec_msg_user_control_released(struct cec_msg *msg)
  1261. {
  1262. msg->len = 2;
  1263. msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;
  1264. }
  1265. /* Remote Control Passthrough Feature */
  1266. /* Power Status Feature */
  1267. static inline void cec_msg_report_power_status(struct cec_msg *msg,
  1268. __u8 pwr_state)
  1269. {
  1270. msg->len = 3;
  1271. msg->msg[1] = CEC_MSG_REPORT_POWER_STATUS;
  1272. msg->msg[2] = pwr_state;
  1273. }
  1274. static inline void cec_ops_report_power_status(const struct cec_msg *msg,
  1275. __u8 *pwr_state)
  1276. {
  1277. *pwr_state = msg->msg[2];
  1278. }
  1279. static inline void cec_msg_give_device_power_status(struct cec_msg *msg,
  1280. bool reply)
  1281. {
  1282. msg->len = 2;
  1283. msg->msg[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
  1284. msg->reply = reply ? CEC_MSG_REPORT_POWER_STATUS : 0;
  1285. }
  1286. /* General Protocol Messages */
  1287. static inline void cec_msg_feature_abort(struct cec_msg *msg,
  1288. __u8 abort_msg, __u8 reason)
  1289. {
  1290. msg->len = 4;
  1291. msg->msg[1] = CEC_MSG_FEATURE_ABORT;
  1292. msg->msg[2] = abort_msg;
  1293. msg->msg[3] = reason;
  1294. }
  1295. static inline void cec_ops_feature_abort(const struct cec_msg *msg,
  1296. __u8 *abort_msg, __u8 *reason)
  1297. {
  1298. *abort_msg = msg->msg[2];
  1299. *reason = msg->msg[3];
  1300. }
  1301. /* This changes the current message into a feature abort message */
  1302. static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
  1303. {
  1304. cec_msg_set_reply_to(msg, msg);
  1305. msg->len = 4;
  1306. msg->msg[2] = msg->msg[1];
  1307. msg->msg[3] = reason;
  1308. msg->msg[1] = CEC_MSG_FEATURE_ABORT;
  1309. }
  1310. static inline void cec_msg_abort(struct cec_msg *msg)
  1311. {
  1312. msg->len = 2;
  1313. msg->msg[1] = CEC_MSG_ABORT;
  1314. }
  1315. /* System Audio Control Feature */
  1316. static inline void cec_msg_report_audio_status(struct cec_msg *msg,
  1317. __u8 aud_mute_status,
  1318. __u8 aud_vol_status)
  1319. {
  1320. msg->len = 3;
  1321. msg->msg[1] = CEC_MSG_REPORT_AUDIO_STATUS;
  1322. msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);
  1323. }
  1324. static inline void cec_ops_report_audio_status(const struct cec_msg *msg,
  1325. __u8 *aud_mute_status,
  1326. __u8 *aud_vol_status)
  1327. {
  1328. *aud_mute_status = msg->msg[2] >> 7;
  1329. *aud_vol_status = msg->msg[2] & 0x7f;
  1330. }
  1331. static inline void cec_msg_give_audio_status(struct cec_msg *msg,
  1332. bool reply)
  1333. {
  1334. msg->len = 2;
  1335. msg->msg[1] = CEC_MSG_GIVE_AUDIO_STATUS;
  1336. msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;
  1337. }
  1338. static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,
  1339. __u8 sys_aud_status)
  1340. {
  1341. msg->len = 3;
  1342. msg->msg[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE;
  1343. msg->msg[2] = sys_aud_status;
  1344. }
  1345. static inline void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
  1346. __u8 *sys_aud_status)
  1347. {
  1348. *sys_aud_status = msg->msg[2];
  1349. }
  1350. static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,
  1351. bool reply,
  1352. __u16 phys_addr)
  1353. {
  1354. msg->len = phys_addr == 0xffff ? 2 : 4;
  1355. msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST;
  1356. msg->msg[2] = phys_addr >> 8;
  1357. msg->msg[3] = phys_addr & 0xff;
  1358. msg->reply = reply ? CEC_MSG_SET_SYSTEM_AUDIO_MODE : 0;
  1359. }
  1360. static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
  1361. __u16 *phys_addr)
  1362. {
  1363. if (msg->len < 4)
  1364. *phys_addr = 0xffff;
  1365. else
  1366. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1367. }
  1368. static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,
  1369. __u8 sys_aud_status)
  1370. {
  1371. msg->len = 3;
  1372. msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS;
  1373. msg->msg[2] = sys_aud_status;
  1374. }
  1375. static inline void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
  1376. __u8 *sys_aud_status)
  1377. {
  1378. *sys_aud_status = msg->msg[2];
  1379. }
  1380. static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
  1381. bool reply)
  1382. {
  1383. msg->len = 2;
  1384. msg->msg[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
  1385. msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;
  1386. }
  1387. static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
  1388. __u8 num_descriptors,
  1389. const __u32 *descriptors)
  1390. {
  1391. unsigned int i;
  1392. if (num_descriptors > 4)
  1393. num_descriptors = 4;
  1394. msg->len = 2 + num_descriptors * 3;
  1395. msg->msg[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR;
  1396. for (i = 0; i < num_descriptors; i++) {
  1397. msg->msg[2 + i * 3] = (descriptors[i] >> 16) & 0xff;
  1398. msg->msg[3 + i * 3] = (descriptors[i] >> 8) & 0xff;
  1399. msg->msg[4 + i * 3] = descriptors[i] & 0xff;
  1400. }
  1401. }
  1402. static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
  1403. __u8 *num_descriptors,
  1404. __u32 *descriptors)
  1405. {
  1406. unsigned int i;
  1407. *num_descriptors = (msg->len - 2) / 3;
  1408. if (*num_descriptors > 4)
  1409. *num_descriptors = 4;
  1410. for (i = 0; i < *num_descriptors; i++)
  1411. descriptors[i] = (msg->msg[2 + i * 3] << 16) |
  1412. (msg->msg[3 + i * 3] << 8) |
  1413. msg->msg[4 + i * 3];
  1414. }
  1415. static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
  1416. bool reply,
  1417. __u8 num_descriptors,
  1418. const __u8 *audio_format_id,
  1419. const __u8 *audio_format_code)
  1420. {
  1421. unsigned int i;
  1422. if (num_descriptors > 4)
  1423. num_descriptors = 4;
  1424. msg->len = 2 + num_descriptors;
  1425. msg->msg[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR;
  1426. msg->reply = reply ? CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR : 0;
  1427. for (i = 0; i < num_descriptors; i++)
  1428. msg->msg[2 + i] = (audio_format_id[i] << 6) |
  1429. (audio_format_code[i] & 0x3f);
  1430. }
  1431. static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
  1432. __u8 *num_descriptors,
  1433. __u8 *audio_format_id,
  1434. __u8 *audio_format_code)
  1435. {
  1436. unsigned int i;
  1437. *num_descriptors = msg->len - 2;
  1438. if (*num_descriptors > 4)
  1439. *num_descriptors = 4;
  1440. for (i = 0; i < *num_descriptors; i++) {
  1441. audio_format_id[i] = msg->msg[2 + i] >> 6;
  1442. audio_format_code[i] = msg->msg[2 + i] & 0x3f;
  1443. }
  1444. }
  1445. /* Audio Rate Control Feature */
  1446. static inline void cec_msg_set_audio_rate(struct cec_msg *msg,
  1447. __u8 audio_rate)
  1448. {
  1449. msg->len = 3;
  1450. msg->msg[1] = CEC_MSG_SET_AUDIO_RATE;
  1451. msg->msg[2] = audio_rate;
  1452. }
  1453. static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,
  1454. __u8 *audio_rate)
  1455. {
  1456. *audio_rate = msg->msg[2];
  1457. }
  1458. /* Audio Return Channel Control Feature */
  1459. static inline void cec_msg_report_arc_initiated(struct cec_msg *msg)
  1460. {
  1461. msg->len = 2;
  1462. msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;
  1463. }
  1464. static inline void cec_msg_initiate_arc(struct cec_msg *msg,
  1465. bool reply)
  1466. {
  1467. msg->len = 2;
  1468. msg->msg[1] = CEC_MSG_INITIATE_ARC;
  1469. msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;
  1470. }
  1471. static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,
  1472. bool reply)
  1473. {
  1474. msg->len = 2;
  1475. msg->msg[1] = CEC_MSG_REQUEST_ARC_INITIATION;
  1476. msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;
  1477. }
  1478. static inline void cec_msg_report_arc_terminated(struct cec_msg *msg)
  1479. {
  1480. msg->len = 2;
  1481. msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;
  1482. }
  1483. static inline void cec_msg_terminate_arc(struct cec_msg *msg,
  1484. bool reply)
  1485. {
  1486. msg->len = 2;
  1487. msg->msg[1] = CEC_MSG_TERMINATE_ARC;
  1488. msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;
  1489. }
  1490. static inline void cec_msg_request_arc_termination(struct cec_msg *msg,
  1491. bool reply)
  1492. {
  1493. msg->len = 2;
  1494. msg->msg[1] = CEC_MSG_REQUEST_ARC_TERMINATION;
  1495. msg->reply = reply ? CEC_MSG_TERMINATE_ARC : 0;
  1496. }
  1497. /* Dynamic Audio Lipsync Feature */
  1498. /* Only for CEC 2.0 and up */
  1499. static inline void cec_msg_report_current_latency(struct cec_msg *msg,
  1500. __u16 phys_addr,
  1501. __u8 video_latency,
  1502. __u8 low_latency_mode,
  1503. __u8 audio_out_compensated,
  1504. __u8 audio_out_delay)
  1505. {
  1506. msg->len = 7;
  1507. msg->msg[0] |= 0xf; /* broadcast */
  1508. msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
  1509. msg->msg[2] = phys_addr >> 8;
  1510. msg->msg[3] = phys_addr & 0xff;
  1511. msg->msg[4] = video_latency;
  1512. msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
  1513. msg->msg[6] = audio_out_delay;
  1514. }
  1515. static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
  1516. __u16 *phys_addr,
  1517. __u8 *video_latency,
  1518. __u8 *low_latency_mode,
  1519. __u8 *audio_out_compensated,
  1520. __u8 *audio_out_delay)
  1521. {
  1522. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1523. *video_latency = msg->msg[4];
  1524. *low_latency_mode = (msg->msg[5] >> 2) & 1;
  1525. *audio_out_compensated = msg->msg[5] & 3;
  1526. *audio_out_delay = msg->msg[6];
  1527. }
  1528. static inline void cec_msg_request_current_latency(struct cec_msg *msg,
  1529. bool reply,
  1530. __u16 phys_addr)
  1531. {
  1532. msg->len = 4;
  1533. msg->msg[0] |= 0xf; /* broadcast */
  1534. msg->msg[1] = CEC_MSG_REQUEST_CURRENT_LATENCY;
  1535. msg->msg[2] = phys_addr >> 8;
  1536. msg->msg[3] = phys_addr & 0xff;
  1537. msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0;
  1538. }
  1539. static inline void cec_ops_request_current_latency(const struct cec_msg *msg,
  1540. __u16 *phys_addr)
  1541. {
  1542. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1543. }
  1544. /* Capability Discovery and Control Feature */
  1545. static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
  1546. __u16 phys_addr1,
  1547. __u16 phys_addr2)
  1548. {
  1549. msg->len = 9;
  1550. msg->msg[0] |= 0xf; /* broadcast */
  1551. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1552. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1553. msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
  1554. msg->msg[5] = phys_addr1 >> 8;
  1555. msg->msg[6] = phys_addr1 & 0xff;
  1556. msg->msg[7] = phys_addr2 >> 8;
  1557. msg->msg[8] = phys_addr2 & 0xff;
  1558. }
  1559. static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
  1560. __u16 *phys_addr,
  1561. __u16 *phys_addr1,
  1562. __u16 *phys_addr2)
  1563. {
  1564. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1565. *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
  1566. *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
  1567. }
  1568. static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
  1569. __u16 target_phys_addr,
  1570. __u8 hec_func_state,
  1571. __u8 host_func_state,
  1572. __u8 enc_func_state,
  1573. __u8 cdc_errcode,
  1574. __u8 has_field,
  1575. __u16 hec_field)
  1576. {
  1577. msg->len = has_field ? 10 : 8;
  1578. msg->msg[0] |= 0xf; /* broadcast */
  1579. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1580. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1581. msg->msg[4] = CEC_MSG_CDC_HEC_REPORT_STATE;
  1582. msg->msg[5] = target_phys_addr >> 8;
  1583. msg->msg[6] = target_phys_addr & 0xff;
  1584. msg->msg[7] = (hec_func_state << 6) |
  1585. (host_func_state << 4) |
  1586. (enc_func_state << 2) |
  1587. cdc_errcode;
  1588. if (has_field) {
  1589. msg->msg[8] = hec_field >> 8;
  1590. msg->msg[9] = hec_field & 0xff;
  1591. }
  1592. }
  1593. static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
  1594. __u16 *phys_addr,
  1595. __u16 *target_phys_addr,
  1596. __u8 *hec_func_state,
  1597. __u8 *host_func_state,
  1598. __u8 *enc_func_state,
  1599. __u8 *cdc_errcode,
  1600. __u8 *has_field,
  1601. __u16 *hec_field)
  1602. {
  1603. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1604. *target_phys_addr = (msg->msg[5] << 8) | msg->msg[6];
  1605. *hec_func_state = msg->msg[7] >> 6;
  1606. *host_func_state = (msg->msg[7] >> 4) & 3;
  1607. *enc_func_state = (msg->msg[7] >> 4) & 3;
  1608. *cdc_errcode = msg->msg[7] & 3;
  1609. *has_field = msg->len >= 10;
  1610. *hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0;
  1611. }
  1612. static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
  1613. __u16 phys_addr1,
  1614. __u16 phys_addr2,
  1615. __u8 hec_set_state,
  1616. __u16 phys_addr3,
  1617. __u16 phys_addr4,
  1618. __u16 phys_addr5)
  1619. {
  1620. msg->len = 10;
  1621. msg->msg[0] |= 0xf; /* broadcast */
  1622. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1623. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1624. msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
  1625. msg->msg[5] = phys_addr1 >> 8;
  1626. msg->msg[6] = phys_addr1 & 0xff;
  1627. msg->msg[7] = phys_addr2 >> 8;
  1628. msg->msg[8] = phys_addr2 & 0xff;
  1629. msg->msg[9] = hec_set_state;
  1630. if (phys_addr3 != CEC_PHYS_ADDR_INVALID) {
  1631. msg->msg[msg->len++] = phys_addr3 >> 8;
  1632. msg->msg[msg->len++] = phys_addr3 & 0xff;
  1633. if (phys_addr4 != CEC_PHYS_ADDR_INVALID) {
  1634. msg->msg[msg->len++] = phys_addr4 >> 8;
  1635. msg->msg[msg->len++] = phys_addr4 & 0xff;
  1636. if (phys_addr5 != CEC_PHYS_ADDR_INVALID) {
  1637. msg->msg[msg->len++] = phys_addr5 >> 8;
  1638. msg->msg[msg->len++] = phys_addr5 & 0xff;
  1639. }
  1640. }
  1641. }
  1642. }
  1643. static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
  1644. __u16 *phys_addr,
  1645. __u16 *phys_addr1,
  1646. __u16 *phys_addr2,
  1647. __u8 *hec_set_state,
  1648. __u16 *phys_addr3,
  1649. __u16 *phys_addr4,
  1650. __u16 *phys_addr5)
  1651. {
  1652. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1653. *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
  1654. *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
  1655. *hec_set_state = msg->msg[9];
  1656. *phys_addr3 = *phys_addr4 = *phys_addr5 = CEC_PHYS_ADDR_INVALID;
  1657. if (msg->len >= 12)
  1658. *phys_addr3 = (msg->msg[10] << 8) | msg->msg[11];
  1659. if (msg->len >= 14)
  1660. *phys_addr4 = (msg->msg[12] << 8) | msg->msg[13];
  1661. if (msg->len >= 16)
  1662. *phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];
  1663. }
  1664. static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
  1665. __u16 phys_addr1,
  1666. __u8 hec_set_state)
  1667. {
  1668. msg->len = 8;
  1669. msg->msg[0] |= 0xf; /* broadcast */
  1670. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1671. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1672. msg->msg[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT;
  1673. msg->msg[5] = phys_addr1 >> 8;
  1674. msg->msg[6] = phys_addr1 & 0xff;
  1675. msg->msg[7] = hec_set_state;
  1676. }
  1677. static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
  1678. __u16 *phys_addr,
  1679. __u16 *phys_addr1,
  1680. __u8 *hec_set_state)
  1681. {
  1682. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1683. *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
  1684. *hec_set_state = msg->msg[7];
  1685. }
  1686. static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
  1687. __u16 phys_addr1,
  1688. __u16 phys_addr2,
  1689. __u16 phys_addr3)
  1690. {
  1691. msg->len = 11;
  1692. msg->msg[0] |= 0xf; /* broadcast */
  1693. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1694. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1695. msg->msg[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION;
  1696. msg->msg[5] = phys_addr1 >> 8;
  1697. msg->msg[6] = phys_addr1 & 0xff;
  1698. msg->msg[7] = phys_addr2 >> 8;
  1699. msg->msg[8] = phys_addr2 & 0xff;
  1700. msg->msg[9] = phys_addr3 >> 8;
  1701. msg->msg[10] = phys_addr3 & 0xff;
  1702. }
  1703. static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
  1704. __u16 *phys_addr,
  1705. __u16 *phys_addr1,
  1706. __u16 *phys_addr2,
  1707. __u16 *phys_addr3)
  1708. {
  1709. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1710. *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
  1711. *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
  1712. *phys_addr3 = (msg->msg[9] << 8) | msg->msg[10];
  1713. }
  1714. static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
  1715. {
  1716. msg->len = 5;
  1717. msg->msg[0] |= 0xf; /* broadcast */
  1718. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1719. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1720. msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE;
  1721. }
  1722. static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
  1723. __u16 *phys_addr)
  1724. {
  1725. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1726. }
  1727. static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)
  1728. {
  1729. msg->len = 5;
  1730. msg->msg[0] |= 0xf; /* broadcast */
  1731. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1732. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1733. msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER;
  1734. }
  1735. static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
  1736. __u16 *phys_addr)
  1737. {
  1738. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1739. }
  1740. static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
  1741. __u8 input_port,
  1742. __u8 hpd_state)
  1743. {
  1744. msg->len = 6;
  1745. msg->msg[0] |= 0xf; /* broadcast */
  1746. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1747. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1748. msg->msg[4] = CEC_MSG_CDC_HPD_SET_STATE;
  1749. msg->msg[5] = (input_port << 4) | hpd_state;
  1750. }
  1751. static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
  1752. __u16 *phys_addr,
  1753. __u8 *input_port,
  1754. __u8 *hpd_state)
  1755. {
  1756. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1757. *input_port = msg->msg[5] >> 4;
  1758. *hpd_state = msg->msg[5] & 0xf;
  1759. }
  1760. static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
  1761. __u8 hpd_state,
  1762. __u8 hpd_error)
  1763. {
  1764. msg->len = 6;
  1765. msg->msg[0] |= 0xf; /* broadcast */
  1766. msg->msg[1] = CEC_MSG_CDC_MESSAGE;
  1767. /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
  1768. msg->msg[4] = CEC_MSG_CDC_HPD_REPORT_STATE;
  1769. msg->msg[5] = (hpd_state << 4) | hpd_error;
  1770. }
  1771. static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
  1772. __u16 *phys_addr,
  1773. __u8 *hpd_state,
  1774. __u8 *hpd_error)
  1775. {
  1776. *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
  1777. *hpd_state = msg->msg[5] >> 4;
  1778. *hpd_error = msg->msg[5] & 0xf;
  1779. }
  1780. #endif