llc.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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 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. void nfc_llc_exit(void)
  25. {
  26. struct nfc_llc_engine *llc_engine, *n;
  27. list_for_each_entry_safe(llc_engine, n, &llc_engines, entry) {
  28. list_del(&llc_engine->entry);
  29. kfree(llc_engine->name);
  30. kfree(llc_engine);
  31. }
  32. }
  33. int nfc_llc_register(const char *name, struct nfc_llc_ops *ops)
  34. {
  35. struct nfc_llc_engine *llc_engine;
  36. llc_engine = kzalloc(sizeof(struct nfc_llc_engine), GFP_KERNEL);
  37. if (llc_engine == NULL)
  38. return -ENOMEM;
  39. llc_engine->name = kstrdup(name, GFP_KERNEL);
  40. if (llc_engine->name == NULL) {
  41. kfree(llc_engine);
  42. return -ENOMEM;
  43. }
  44. llc_engine->ops = ops;
  45. INIT_LIST_HEAD(&llc_engine->entry);
  46. list_add_tail(&llc_engine->entry, &llc_engines);
  47. return 0;
  48. }
  49. static struct nfc_llc_engine *nfc_llc_name_to_engine(const char *name)
  50. {
  51. struct nfc_llc_engine *llc_engine;
  52. list_for_each_entry(llc_engine, &llc_engines, entry) {
  53. if (strcmp(llc_engine->name, name) == 0)
  54. return llc_engine;
  55. }
  56. return NULL;
  57. }
  58. void nfc_llc_unregister(const char *name)
  59. {
  60. struct nfc_llc_engine *llc_engine;
  61. llc_engine = nfc_llc_name_to_engine(name);
  62. if (llc_engine == NULL)
  63. return;
  64. list_del(&llc_engine->entry);
  65. kfree(llc_engine->name);
  66. kfree(llc_engine);
  67. }
  68. struct nfc_llc *nfc_llc_allocate(const char *name, struct nfc_hci_dev *hdev,
  69. xmit_to_drv_t xmit_to_drv,
  70. rcv_to_hci_t rcv_to_hci, int tx_headroom,
  71. int tx_tailroom, llc_failure_t llc_failure)
  72. {
  73. struct nfc_llc_engine *llc_engine;
  74. struct nfc_llc *llc;
  75. llc_engine = nfc_llc_name_to_engine(name);
  76. if (llc_engine == NULL)
  77. return NULL;
  78. llc = kzalloc(sizeof(struct nfc_llc), GFP_KERNEL);
  79. if (llc == NULL)
  80. return NULL;
  81. llc->data = llc_engine->ops->init(hdev, xmit_to_drv, rcv_to_hci,
  82. tx_headroom, tx_tailroom,
  83. &llc->rx_headroom, &llc->rx_tailroom,
  84. llc_failure);
  85. if (llc->data == NULL) {
  86. kfree(llc);
  87. return NULL;
  88. }
  89. llc->ops = llc_engine->ops;
  90. return llc;
  91. }
  92. void nfc_llc_free(struct nfc_llc *llc)
  93. {
  94. llc->ops->deinit(llc);
  95. kfree(llc);
  96. }
  97. int nfc_llc_start(struct nfc_llc *llc)
  98. {
  99. return llc->ops->start(llc);
  100. }
  101. EXPORT_SYMBOL(nfc_llc_start);
  102. int nfc_llc_stop(struct nfc_llc *llc)
  103. {
  104. return llc->ops->stop(llc);
  105. }
  106. EXPORT_SYMBOL(nfc_llc_stop);
  107. void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb)
  108. {
  109. llc->ops->rcv_from_drv(llc, skb);
  110. }
  111. int nfc_llc_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb)
  112. {
  113. return llc->ops->xmit_from_hci(llc, skb);
  114. }
  115. void *nfc_llc_get_data(struct nfc_llc *llc)
  116. {
  117. return llc->data;
  118. }