17c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo/* 27c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * net/dccp/ccid.c 37c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * 47c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * An implementation of the DCCP protocol 57c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 67c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * 77c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * CCID infrastructure 87c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * 97c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * This program is free software; you can redistribute it and/or modify it 107c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * under the terms of the GNU General Public License version 2 as 117c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * published by the Free Software Foundation. 127c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo */ 137c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 145a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo 167c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo#include "ccid.h" 17129fa44785a399248ae2466b6cb5c655e96668f7Gerrit Renker#include "ccids/lib/tfrc.h" 187c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 19ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkerstatic struct ccid_operations *ccids[] = { 20ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker &ccid2_ops, 21ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker#ifdef CONFIG_IP_DCCP_CCID3 22ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker &ccid3_ops, 23ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker#endif 24ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker}; 25ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 26ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkerstatic struct ccid_operations *ccid_by_number(const u8 id) 27ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker{ 28ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker int i; 29ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 30ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker for (i = 0; i < ARRAY_SIZE(ccids); i++) 31ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker if (ccids[i]->ccid_id == id) 32ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return ccids[i]; 33ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return NULL; 34ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker} 35ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 36ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker/* check that up to @array_len members in @ccid_array are supported */ 37ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkerbool ccid_support_check(u8 const *ccid_array, u8 array_len) 38ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker{ 39ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker while (array_len > 0) 40ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker if (ccid_by_number(ccid_array[--array_len]) == NULL) 41ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return false; 42ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return true; 43ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker} 44ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 45ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker/** 46ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker * ccid_get_builtin_ccids - Populate a list of built-in CCIDs 47ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker * @ccid_array: pointer to copy into 48ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker * @array_len: value to return length into 492c53040f018b6c36a46eec75b9b937aaa5f78e6dBen Hutchings * 50ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker * This function allocates memory - caller must see that it is freed after use. 51ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker */ 52ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkerint ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len) 53ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker{ 54ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker *ccid_array = kmalloc(ARRAY_SIZE(ccids), gfp_any()); 55ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker if (*ccid_array == NULL) 56ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return -ENOBUFS; 57ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 58ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker for (*array_len = 0; *array_len < ARRAY_SIZE(ccids); *array_len += 1) 59ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker (*ccid_array)[*array_len] = ccids[*array_len]->ccid_id; 60ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return 0; 61ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker} 62ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 63ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkerint ccid_getsockopt_builtin_ccids(struct sock *sk, int len, 64ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker char __user *optval, int __user *optlen) 65ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker{ 66ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker u8 *ccid_array, array_len; 67ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker int err = 0; 68ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 69ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker if (ccid_get_builtin_ccids(&ccid_array, &array_len)) 70ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return -ENOBUFS; 71ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 7269a6a0b38a139ccceef32222108caca8a9b0b795Gerrit Renker if (put_user(array_len, optlen)) 7369a6a0b38a139ccceef32222108caca8a9b0b795Gerrit Renker err = -EFAULT; 7469a6a0b38a139ccceef32222108caca8a9b0b795Gerrit Renker else if (len > 0 && copy_to_user(optval, ccid_array, 7569a6a0b38a139ccceef32222108caca8a9b0b795Gerrit Renker len > array_len ? array_len : len)) 76ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker err = -EFAULT; 77ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 78ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker kfree(ccid_array); 79ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return err; 80ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker} 81ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 82de4ef86cfce60d2250111f34f8a084e769f23b16Neil Hormanstatic struct kmem_cache *ccid_kmem_cache_create(int obj_size, char *slab_name_fmt, const char *fmt,...) 837c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{ 84e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameter struct kmem_cache *slab; 8591f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo va_list args; 8691f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo 8791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo va_start(args, fmt); 888ed030dd0aa400d18c63861c2c6deb7c38f4eddeGerrit Renker vsnprintf(slab_name_fmt, CCID_SLAB_NAME_LENGTH, fmt, args); 8991f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo va_end(args); 9091f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo 91de4ef86cfce60d2250111f34f8a084e769f23b16Neil Horman slab = kmem_cache_create(slab_name_fmt, sizeof(struct ccid) + obj_size, 0, 9220c2df83d25c6a95affe6157a4c9cac4cf5ffaacPaul Mundt SLAB_HWCACHE_ALIGN, NULL); 9391f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo return slab; 9491f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo} 9591f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo 96e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstatic void ccid_kmem_cache_destroy(struct kmem_cache *slab) 9791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo{ 98de4ef86cfce60d2250111f34f8a084e769f23b16Neil Horman if (slab != NULL) 9991f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo kmem_cache_destroy(slab); 10091f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo} 10191f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo 102e500f488c27659bb6f5d313b336621f3daa67701Fabian Frederickstatic int __init ccid_activate(struct ccid_operations *ccid_ops) 10391f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo{ 10491f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo int err = -ENOBUFS; 10591f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo 10691f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_ops->ccid_hc_rx_slab = 10791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size, 108de4ef86cfce60d2250111f34f8a084e769f23b16Neil Horman ccid_ops->ccid_hc_rx_slab_name, 10984a97b0af8c29aa5a47cc5271968a9c6004fb91eGerrit Renker "ccid%u_hc_rx_sock", 11084a97b0af8c29aa5a47cc5271968a9c6004fb91eGerrit Renker ccid_ops->ccid_id); 11191f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo if (ccid_ops->ccid_hc_rx_slab == NULL) 11291f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo goto out; 11391f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo 11491f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_ops->ccid_hc_tx_slab = 11591f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size, 116de4ef86cfce60d2250111f34f8a084e769f23b16Neil Horman ccid_ops->ccid_hc_tx_slab_name, 11784a97b0af8c29aa5a47cc5271968a9c6004fb91eGerrit Renker "ccid%u_hc_tx_sock", 11884a97b0af8c29aa5a47cc5271968a9c6004fb91eGerrit Renker ccid_ops->ccid_id); 11991f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo if (ccid_ops->ccid_hc_tx_slab == NULL) 12091f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo goto out_free_rx_slab; 1217c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 1221fd9d2081a9d8d77e5afccd5aafd28310cab3bfcGerrit Renker pr_info("DCCP: Activated CCID %d (%s)\n", 12391f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_ops->ccid_id, ccid_ops->ccid_name); 124ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker err = 0; 12591f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Meloout: 1267c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo return err; 12791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Meloout_free_rx_slab: 12891f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); 12991f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_ops->ccid_hc_rx_slab = NULL; 13091f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo goto out; 1317c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo} 1327c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 133ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkerstatic void ccid_deactivate(struct ccid_operations *ccid_ops) 1347c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{ 13591f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab); 13691f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_ops->ccid_hc_tx_slab = NULL; 13791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); 13891f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_ops->ccid_hc_rx_slab = NULL; 13991f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo 1401fd9d2081a9d8d77e5afccd5aafd28310cab3bfcGerrit Renker pr_info("DCCP: Deactivated CCID %d (%s)\n", 14191f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_ops->ccid_id, ccid_ops->ccid_name); 1427c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo} 1437c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 144e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renkerstruct ccid *ccid_new(const u8 id, struct sock *sk, bool rx) 1457c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{ 146ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker struct ccid_operations *ccid_ops = ccid_by_number(id); 14791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo struct ccid *ccid = NULL; 1487c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 14991f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo if (ccid_ops == NULL) 150ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker goto out; 1517c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 15291f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab : 153e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker ccid_ops->ccid_hc_tx_slab, gfp_any()); 15491f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo if (ccid == NULL) 155ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker goto out; 15691f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid->ccid_ops = ccid_ops; 15791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo if (rx) { 15891f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size); 15991f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo if (ccid->ccid_ops->ccid_hc_rx_init != NULL && 16091f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0) 16191f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo goto out_free_ccid; 16291f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo } else { 16391f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size); 16491f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo if (ccid->ccid_ops->ccid_hc_tx_init != NULL && 16591f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0) 16691f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo goto out_free_ccid; 16791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo } 1687c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Meloout: 1697c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo return ccid; 17091f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Meloout_free_ccid: 17191f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab : 17291f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo ccid_ops->ccid_hc_tx_slab, ccid); 1737c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo ccid = NULL; 1747c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo goto out; 1757c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo} 1767c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 17791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melovoid ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk) 17891f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo{ 179e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker if (ccid != NULL) { 180e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker if (ccid->ccid_ops->ccid_hc_rx_exit != NULL) 181e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker ccid->ccid_ops->ccid_hc_rx_exit(sk); 182e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker kmem_cache_free(ccid->ccid_ops->ccid_hc_rx_slab, ccid); 183e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker } 18491f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo} 1857c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 18691f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melovoid ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk) 18791f0ebf7b6d5cb2b6e818d48587566144821babeArnaldo Carvalho de Melo{ 188e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker if (ccid != NULL) { 189e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker if (ccid->ccid_ops->ccid_hc_tx_exit != NULL) 190e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker ccid->ccid_ops->ccid_hc_tx_exit(sk); 191e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker kmem_cache_free(ccid->ccid_ops->ccid_hc_tx_slab, ccid); 192e5fd56ca4eb3a130882bbef69d6952ef6aca5c8dGerrit Renker } 1937c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo} 1947c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo 195ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkerint __init ccid_initialize_builtins(void) 196ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker{ 197129fa44785a399248ae2466b6cb5c655e96668f7Gerrit Renker int i, err = tfrc_lib_init(); 198129fa44785a399248ae2466b6cb5c655e96668f7Gerrit Renker 199129fa44785a399248ae2466b6cb5c655e96668f7Gerrit Renker if (err) 200129fa44785a399248ae2466b6cb5c655e96668f7Gerrit Renker return err; 201ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 202ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker for (i = 0; i < ARRAY_SIZE(ccids); i++) { 203ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker err = ccid_activate(ccids[i]); 204ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker if (err) 205ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker goto unwind_registrations; 206ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker } 207ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return 0; 208ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 209ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkerunwind_registrations: 210ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker while(--i >= 0) 211ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker ccid_deactivate(ccids[i]); 212129fa44785a399248ae2466b6cb5c655e96668f7Gerrit Renker tfrc_lib_exit(); 213ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker return err; 214ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker} 215ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 216ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renkervoid ccid_cleanup_builtins(void) 217ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker{ 218ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker int i; 219ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker 220ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker for (i = 0; i < ARRAY_SIZE(ccids); i++) 221ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker ccid_deactivate(ccids[i]); 222129fa44785a399248ae2466b6cb5c655e96668f7Gerrit Renker tfrc_lib_exit(); 223ddebc973c56b51b4e5d84d606f0430d81b895d67Gerrit Renker} 224