llc.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Link Layer Control manager
  4. *
  5. * Copyright (C) 2012 Intel Corporation. All rights reserved.
  6. */
  7. #include <net/nfc/llc.h>
  8. #include "llc.h"
  9. static LIST_HEAD(llc_engines);
  10. int __init nfc_llc_init(void)
  11. {
  12. int r;
  13. r = nfc_llc_nop_register();
  14. if (r)
  15. goto exit;
  16. r = nfc_llc_shdlc_register();
  17. if (r)
  18. goto exit;
  19. return 0;
  20. exit:
  21. nfc_llc_exit();
  22. return r;
  23. }
  24. static void nfc_llc_del_engine(struct nfc_llc_engine *llc_engine)
  25. {
  26. list_del(&llc_engine->entry);
  27. kfree_const(llc_engine->name);
  28. kfree(llc_engine);
  29. }
  30. void nfc_llc_exit(void)
  31. {
  32. struct nfc_llc_engine *llc_engine, *n;
  33. list_for_each_entry_safe(llc_engine, n, &llc_engines, entry)
  34. nfc_llc_del_engine(llc_engine);
  35. }
  36. int nfc_llc_register(const char *name, const struct nfc_llc_ops *ops)
  37. {
  38. struct nfc_llc_engine *llc_engine;
  39. llc_engine = kzalloc(sizeof(struct nfc_llc_engine), GFP_KERNEL);
  40. if (llc_engine == NULL)
  41. return -ENOMEM;
  42. llc_engine->name = kstrdup_const(name, GFP_KERNEL);
  43. if (llc_engine->name == NULL) {
  44. kfree(llc_engine);
  45. return -ENOMEM;
  46. }
  47. llc_engine->ops = ops;
  48. INIT_LIST_HEAD(&llc_engine->entry);
  49. list_add_tail(&llc_engine->entry, &llc_engines);
  50. return 0;
  51. }
  52. static struct nfc_llc_engine *nfc_llc_name_to_engine(const char *name)
  53. {
  54. struct nfc_llc_engine *llc_engine;
  55. list_for_each_entry(llc_engine, &llc_engines, entry) {
  56. if (strcmp(llc_engine->name, name) == 0)
  57. return llc_engine;
  58. }
  59. return NULL;
  60. }
  61. void nfc_llc_unregister(const char *name)
  62. {
  63. struct nfc_llc_engine *llc_engine;
  64. llc_engine = nfc_llc_name_to_engine(name);
  65. if (llc_engine == NULL)
  66. return;
  67. nfc_llc_del_engine(llc_engine);
  68. }
  69. struct nfc_llc *nfc_llc_allocate(const char *name, struct nfc_hci_dev *hdev,
  70. xmit_to_drv_t xmit_to_drv,
  71. rcv_to_hci_t rcv_to_hci, int tx_headroom,
  72. int tx_tailroom, llc_failure_t llc_failure)
  73. {
  74. struct nfc_llc_engine *llc_engine;
  75. struct nfc_llc *llc;
  76. llc_engine = nfc_llc_name_to_engine(name);
  77. if (llc_engine == NULL)
  78. return NULL;
  79. llc = kzalloc(sizeof(struct nfc_llc), GFP_KERNEL);
  80. if (llc == NULL)
  81. return NULL;
  82. llc->data = llc_engine->ops->init(hdev, xmit_to_drv, rcv_to_hci,
  83. tx_headroom, tx_tailroom,
  84. &llc->rx_headroom, &llc->rx_tailroom,
  85. llc_failure);
  86. if (llc->data == NULL) {
  87. kfree(llc);
  88. return NULL;
  89. }
  90. llc->ops = llc_engine->ops;
  91. return llc;
  92. }
  93. void nfc_llc_free(struct nfc_llc *llc)
  94. {
  95. llc->ops->deinit(llc);
  96. kfree(llc);
  97. }
  98. int nfc_llc_start(struct nfc_llc *llc)
  99. {
  100. return llc->ops->start(llc);
  101. }
  102. EXPORT_SYMBOL(nfc_llc_start);
  103. int nfc_llc_stop(struct nfc_llc *llc)
  104. {
  105. return llc->ops->stop(llc);
  106. }
  107. EXPORT_SYMBOL(nfc_llc_stop);
  108. void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb)
  109. {
  110. llc->ops->rcv_from_drv(llc, skb);
  111. }
  112. int nfc_llc_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb)
  113. {
  114. return llc->ops->xmit_from_hci(llc, skb);
  115. }
  116. void *nfc_llc_get_data(struct nfc_llc *llc)
  117. {
  118. return llc->data;
  119. }