cec-funcs.h 51 KB

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