msm_hdcp.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
  5. */
  6. #define pr_fmt(fmt) "[msm-hdcp] %s: " fmt, __func__
  7. #include <linux/platform_device.h>
  8. #include <linux/kernel.h>
  9. #include <linux/slab.h>
  10. #include <linux/module.h>
  11. #include <linux/fs.h>
  12. #include <linux/file.h>
  13. #include <linux/uaccess.h>
  14. #include <linux/cdev.h>
  15. #include <linux/list.h>
  16. #include <linux/device.h>
  17. #include <linux/errno.h>
  18. #include <linux/msm_hdcp.h>
  19. #include <linux/of.h>
  20. #define CLASS_NAME "hdcp"
  21. #define DRIVER_NAME "msm_hdcp"
  22. struct msm_hdcp {
  23. struct platform_device *pdev;
  24. dev_t dev_num;
  25. struct cdev cdev;
  26. struct class *class;
  27. struct device *device;
  28. struct HDCP_V2V1_MSG_TOPOLOGY cached_tp;
  29. u32 tp_msgid;
  30. void *client_ctx;
  31. void (*cb)(void *ctx, u8 data);
  32. };
  33. void msm_hdcp_register_cb(struct device *dev, void *ctx,
  34. void (*cb)(void *ctx, u8 data))
  35. {
  36. struct msm_hdcp *hdcp = NULL;
  37. if (!dev) {
  38. pr_err("invalid device pointer\n");
  39. return;
  40. }
  41. hdcp = dev_get_drvdata(dev);
  42. if (!hdcp) {
  43. pr_err("invalid driver pointer\n");
  44. return;
  45. }
  46. hdcp->cb = cb;
  47. hdcp->client_ctx = ctx;
  48. }
  49. EXPORT_SYMBOL(msm_hdcp_register_cb);
  50. void msm_hdcp_notify_topology(struct device *dev)
  51. {
  52. char *envp[4];
  53. char tp[SZ_16];
  54. char ver[SZ_16];
  55. struct msm_hdcp *hdcp = NULL;
  56. if (!dev) {
  57. pr_err("invalid device pointer\n");
  58. return;
  59. }
  60. hdcp = dev_get_drvdata(dev);
  61. if (!hdcp) {
  62. pr_err("invalid driver pointer\n");
  63. return;
  64. }
  65. snprintf(tp, SZ_16, "%d", DOWN_CHECK_TOPOLOGY);
  66. snprintf(ver, SZ_16, "%d", HDCP_V1_TX);
  67. envp[0] = "HDCP_MGR_EVENT=MSG_READY";
  68. envp[1] = tp;
  69. envp[2] = ver;
  70. envp[3] = NULL;
  71. kobject_uevent_env(&hdcp->device->kobj, KOBJ_CHANGE, envp);
  72. }
  73. EXPORT_SYMBOL(msm_hdcp_notify_topology);
  74. void msm_hdcp_cache_repeater_topology(struct device *dev,
  75. struct HDCP_V2V1_MSG_TOPOLOGY *tp)
  76. {
  77. struct msm_hdcp *hdcp = NULL;
  78. if (!dev || !tp) {
  79. pr_err("invalid input\n");
  80. return;
  81. }
  82. hdcp = dev_get_drvdata(dev);
  83. if (!hdcp) {
  84. pr_err("invalid driver pointer\n");
  85. return;
  86. }
  87. memcpy(&hdcp->cached_tp, tp,
  88. sizeof(struct HDCP_V2V1_MSG_TOPOLOGY));
  89. }
  90. EXPORT_SYMBOL(msm_hdcp_cache_repeater_topology);
  91. static ssize_t tp_show(struct device *dev, struct device_attribute *attr,
  92. char *buf)
  93. {
  94. ssize_t ret = 0;
  95. struct msm_hdcp *hdcp = NULL;
  96. if (!dev) {
  97. pr_err("invalid device pointer\n");
  98. return -ENODEV;
  99. }
  100. hdcp = dev_get_drvdata(dev);
  101. if (!hdcp) {
  102. pr_err("invalid driver pointer\n");
  103. return -ENODEV;
  104. }
  105. switch (hdcp->tp_msgid) {
  106. case DOWN_CHECK_TOPOLOGY:
  107. case DOWN_REQUEST_TOPOLOGY:
  108. buf[MSG_ID_IDX] = hdcp->tp_msgid;
  109. buf[RET_CODE_IDX] = HDCP_AUTHED;
  110. ret = HEADER_LEN;
  111. memcpy(buf + HEADER_LEN, &hdcp->cached_tp,
  112. sizeof(struct HDCP_V2V1_MSG_TOPOLOGY));
  113. ret += sizeof(struct HDCP_V2V1_MSG_TOPOLOGY);
  114. /* reset the flag once the data is written back to user space */
  115. hdcp->tp_msgid = DOWN_REQUEST_TOPOLOGY;
  116. break;
  117. default:
  118. ret = -EINVAL;
  119. }
  120. return ret;
  121. }
  122. static ssize_t tp_store(struct device *dev, struct device_attribute *attr,
  123. const char *buf, size_t count)
  124. {
  125. int msgid = 0;
  126. ssize_t ret = count;
  127. struct msm_hdcp *hdcp = NULL;
  128. if (!dev) {
  129. pr_err("invalid device pointer\n");
  130. return -ENODEV;
  131. }
  132. hdcp = dev_get_drvdata(dev);
  133. if (!hdcp) {
  134. pr_err("invalid driver pointer\n");
  135. return -ENODEV;
  136. }
  137. msgid = buf[0];
  138. switch (msgid) {
  139. case DOWN_CHECK_TOPOLOGY:
  140. case DOWN_REQUEST_TOPOLOGY:
  141. hdcp->tp_msgid = msgid;
  142. break;
  143. default:
  144. ret = -EINVAL;
  145. }
  146. return ret;
  147. }
  148. static ssize_t min_level_change_store(struct device *dev,
  149. struct device_attribute *attr, const char *buf, size_t count)
  150. {
  151. int rc;
  152. int min_enc_lvl;
  153. ssize_t ret = count;
  154. struct msm_hdcp *hdcp = NULL;
  155. if (!dev) {
  156. pr_err("invalid device pointer\n");
  157. return -ENODEV;
  158. }
  159. hdcp = dev_get_drvdata(dev);
  160. if (!hdcp) {
  161. pr_err("invalid driver pointer\n");
  162. return -ENODEV;
  163. }
  164. rc = kstrtoint(buf, 10, &min_enc_lvl);
  165. if (rc) {
  166. pr_err("kstrtoint failed. rc=%d\n", rc);
  167. return -EINVAL;
  168. }
  169. if (hdcp->cb && hdcp->client_ctx)
  170. hdcp->cb(hdcp->client_ctx, min_enc_lvl);
  171. return ret;
  172. }
  173. static DEVICE_ATTR_RW(tp);
  174. static DEVICE_ATTR_WO(min_level_change);
  175. static struct attribute *msm_hdcp_fs_attrs[] = {
  176. &dev_attr_tp.attr,
  177. &dev_attr_min_level_change.attr,
  178. NULL
  179. };
  180. static struct attribute_group msm_hdcp_fs_attr_group = {
  181. .attrs = msm_hdcp_fs_attrs
  182. };
  183. static int msm_hdcp_open(struct inode *inode, struct file *file)
  184. {
  185. return 0;
  186. }
  187. static int msm_hdcp_close(struct inode *inode, struct file *file)
  188. {
  189. return 0;
  190. }
  191. static const struct file_operations msm_hdcp_fops = {
  192. .owner = THIS_MODULE,
  193. .open = msm_hdcp_open,
  194. .release = msm_hdcp_close,
  195. };
  196. static const struct of_device_id msm_hdcp_dt_match[] = {
  197. { .compatible = "qcom,msm-hdcp",},
  198. {}
  199. };
  200. MODULE_DEVICE_TABLE(of, msm_hdcp_dt_match);
  201. static int msm_hdcp_probe(struct platform_device *pdev)
  202. {
  203. int ret;
  204. struct msm_hdcp *hdcp;
  205. hdcp = devm_kzalloc(&pdev->dev, sizeof(struct msm_hdcp), GFP_KERNEL);
  206. if (!hdcp)
  207. return -ENOMEM;
  208. hdcp->pdev = pdev;
  209. platform_set_drvdata(pdev, hdcp);
  210. ret = alloc_chrdev_region(&hdcp->dev_num, 0, 1, DRIVER_NAME);
  211. if (ret < 0) {
  212. pr_err("alloc_chrdev_region failed ret = %d\n", ret);
  213. return ret;
  214. }
  215. hdcp->class = class_create(THIS_MODULE, CLASS_NAME);
  216. if (IS_ERR(hdcp->class)) {
  217. ret = PTR_ERR(hdcp->class);
  218. pr_err("couldn't create class rc = %d\n", ret);
  219. goto error_class_create;
  220. }
  221. hdcp->device = device_create(hdcp->class, NULL,
  222. hdcp->dev_num, hdcp, DRIVER_NAME);
  223. if (IS_ERR(hdcp->device)) {
  224. ret = PTR_ERR(hdcp->device);
  225. pr_err("device_create failed %d\n", ret);
  226. goto error_class_device_create;
  227. }
  228. cdev_init(&hdcp->cdev, &msm_hdcp_fops);
  229. ret = cdev_add(&hdcp->cdev, MKDEV(MAJOR(hdcp->dev_num), 0), 1);
  230. if (ret < 0) {
  231. pr_err("cdev_add failed %d\n", ret);
  232. goto error_cdev_add;
  233. }
  234. ret = sysfs_create_group(&hdcp->device->kobj, &msm_hdcp_fs_attr_group);
  235. if (ret)
  236. pr_err("unable to register msm_hdcp sysfs nodes\n");
  237. hdcp->tp_msgid = DOWN_REQUEST_TOPOLOGY;
  238. return 0;
  239. error_cdev_add:
  240. device_destroy(hdcp->class, hdcp->dev_num);
  241. error_class_device_create:
  242. class_destroy(hdcp->class);
  243. error_class_create:
  244. unregister_chrdev_region(hdcp->dev_num, 1);
  245. return ret;
  246. }
  247. static int msm_hdcp_remove(struct platform_device *pdev)
  248. {
  249. struct msm_hdcp *hdcp;
  250. hdcp = platform_get_drvdata(pdev);
  251. if (!hdcp)
  252. return -ENODEV;
  253. sysfs_remove_group(&hdcp->device->kobj,
  254. &msm_hdcp_fs_attr_group);
  255. cdev_del(&hdcp->cdev);
  256. device_destroy(hdcp->class, hdcp->dev_num);
  257. class_destroy(hdcp->class);
  258. unregister_chrdev_region(hdcp->dev_num, 1);
  259. return 0;
  260. }
  261. static struct platform_driver msm_hdcp_driver = {
  262. .probe = msm_hdcp_probe,
  263. .remove = msm_hdcp_remove,
  264. .driver = {
  265. .name = "msm_hdcp",
  266. .of_match_table = msm_hdcp_dt_match,
  267. .pm = NULL,
  268. }
  269. };
  270. void __init msm_hdcp_register(void)
  271. {
  272. platform_driver_register(&msm_hdcp_driver);
  273. }
  274. void __exit msm_hdcp_unregister(void)
  275. {
  276. platform_driver_unregister(&msm_hdcp_driver);
  277. }