0001
0002
0003
0004
0005
0006
0007
0008 #include <net/nfc/llc.h>
0009
0010 #include "llc.h"
0011
0012 static LIST_HEAD(llc_engines);
0013
0014 int __init nfc_llc_init(void)
0015 {
0016 int r;
0017
0018 r = nfc_llc_nop_register();
0019 if (r)
0020 goto exit;
0021
0022 r = nfc_llc_shdlc_register();
0023 if (r)
0024 goto exit;
0025
0026 return 0;
0027
0028 exit:
0029 nfc_llc_exit();
0030 return r;
0031 }
0032
0033 void nfc_llc_exit(void)
0034 {
0035 struct nfc_llc_engine *llc_engine, *n;
0036
0037 list_for_each_entry_safe(llc_engine, n, &llc_engines, entry) {
0038 list_del(&llc_engine->entry);
0039 kfree(llc_engine->name);
0040 kfree(llc_engine);
0041 }
0042 }
0043
0044 int nfc_llc_register(const char *name, const struct nfc_llc_ops *ops)
0045 {
0046 struct nfc_llc_engine *llc_engine;
0047
0048 llc_engine = kzalloc(sizeof(struct nfc_llc_engine), GFP_KERNEL);
0049 if (llc_engine == NULL)
0050 return -ENOMEM;
0051
0052 llc_engine->name = kstrdup(name, GFP_KERNEL);
0053 if (llc_engine->name == NULL) {
0054 kfree(llc_engine);
0055 return -ENOMEM;
0056 }
0057 llc_engine->ops = ops;
0058
0059 INIT_LIST_HEAD(&llc_engine->entry);
0060 list_add_tail(&llc_engine->entry, &llc_engines);
0061
0062 return 0;
0063 }
0064
0065 static struct nfc_llc_engine *nfc_llc_name_to_engine(const char *name)
0066 {
0067 struct nfc_llc_engine *llc_engine;
0068
0069 list_for_each_entry(llc_engine, &llc_engines, entry) {
0070 if (strcmp(llc_engine->name, name) == 0)
0071 return llc_engine;
0072 }
0073
0074 return NULL;
0075 }
0076
0077 void nfc_llc_unregister(const char *name)
0078 {
0079 struct nfc_llc_engine *llc_engine;
0080
0081 llc_engine = nfc_llc_name_to_engine(name);
0082 if (llc_engine == NULL)
0083 return;
0084
0085 list_del(&llc_engine->entry);
0086 kfree(llc_engine->name);
0087 kfree(llc_engine);
0088 }
0089
0090 struct nfc_llc *nfc_llc_allocate(const char *name, struct nfc_hci_dev *hdev,
0091 xmit_to_drv_t xmit_to_drv,
0092 rcv_to_hci_t rcv_to_hci, int tx_headroom,
0093 int tx_tailroom, llc_failure_t llc_failure)
0094 {
0095 struct nfc_llc_engine *llc_engine;
0096 struct nfc_llc *llc;
0097
0098 llc_engine = nfc_llc_name_to_engine(name);
0099 if (llc_engine == NULL)
0100 return NULL;
0101
0102 llc = kzalloc(sizeof(struct nfc_llc), GFP_KERNEL);
0103 if (llc == NULL)
0104 return NULL;
0105
0106 llc->data = llc_engine->ops->init(hdev, xmit_to_drv, rcv_to_hci,
0107 tx_headroom, tx_tailroom,
0108 &llc->rx_headroom, &llc->rx_tailroom,
0109 llc_failure);
0110 if (llc->data == NULL) {
0111 kfree(llc);
0112 return NULL;
0113 }
0114 llc->ops = llc_engine->ops;
0115
0116 return llc;
0117 }
0118
0119 void nfc_llc_free(struct nfc_llc *llc)
0120 {
0121 llc->ops->deinit(llc);
0122 kfree(llc);
0123 }
0124
0125 int nfc_llc_start(struct nfc_llc *llc)
0126 {
0127 return llc->ops->start(llc);
0128 }
0129 EXPORT_SYMBOL(nfc_llc_start);
0130
0131 int nfc_llc_stop(struct nfc_llc *llc)
0132 {
0133 return llc->ops->stop(llc);
0134 }
0135 EXPORT_SYMBOL(nfc_llc_stop);
0136
0137 void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb)
0138 {
0139 llc->ops->rcv_from_drv(llc, skb);
0140 }
0141
0142 int nfc_llc_xmit_from_hci(struct nfc_llc *llc, struct sk_buff *skb)
0143 {
0144 return llc->ops->xmit_from_hci(llc, skb);
0145 }
0146
0147 void *nfc_llc_get_data(struct nfc_llc *llc)
0148 {
0149 return llc->data;
0150 }