18e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HIDP implementation for Linux Bluetooth stack (BlueZ). 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License version 2 as 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds published by the Free Software Foundation; 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 138e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 148e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 158e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 188e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 198e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFTWARE IS DISCLAIMED. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 238c520a59927a5600973782505dbb750d985057c4Gustavo Padovan#include <linux/export.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/file.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hidp.h" 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATOstatic struct bt_sock_list hidp_sk_list = { 295c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO .lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock) 305c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO}; 315c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hidp_sock_release(struct socket *sock) 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sock %p sk %p", sock, sk); 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sk) 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 415c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO bt_sock_unlink(&hidp_sk_list, sk); 425c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_orphan(sk); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_put(sk); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *argp = (void __user *) arg; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hidp_connadd_req ca; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hidp_conndel_req cd; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hidp_connlist_req cl; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hidp_conninfo ci; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct socket *csock; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct socket *isock; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("cmd %x arg %lx", cmd, arg); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HIDPCONNADD: 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_NET_ADMIN)) 65bf5b30b8a4416de04f1ac1196281ddb318669464Zhao Hongjiang return -EPERM; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&ca, argp, sizeof(ca))) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csock = sockfd_lookup(ca.ctrl_sock, &err); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!csock) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isock = sockfd_lookup(ca.intr_sock, &err); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!isock) { 7667b23219ce2f78352b0c566a472ff16c1b0fea9aJulia Lawall sockfd_put(csock); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 805205185d461d5902325e457ca80bd421127b7308David Herrmann err = hidp_connection_add(&ca, csock, isock); 815205185d461d5902325e457ca80bd421127b7308David Herrmann if (!err && copy_to_user(argp, &ca, sizeof(ca))) 825205185d461d5902325e457ca80bd421127b7308David Herrmann err = -EFAULT; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 845205185d461d5902325e457ca80bd421127b7308David Herrmann sockfd_put(csock); 855205185d461d5902325e457ca80bd421127b7308David Herrmann sockfd_put(isock); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HIDPCONNDEL: 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_NET_ADMIN)) 91bf5b30b8a4416de04f1ac1196281ddb318669464Zhao Hongjiang return -EPERM; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&cd, argp, sizeof(cd))) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 965205185d461d5902325e457ca80bd421127b7308David Herrmann return hidp_connection_del(&cd); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HIDPGETCONNLIST: 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&cl, argp, sizeof(cl))) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cl.cnum <= 0) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = hidp_get_connlist(&cl); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!err && copy_to_user(argp, &cl, sizeof(cl))) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case HIDPGETCONNINFO: 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&ci, argp, sizeof(ci))) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = hidp_get_conninfo(&ci); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!err && copy_to_user(argp, &ci, sizeof(ci))) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 125e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann#ifdef CONFIG_COMPAT 126e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmannstruct compat_hidp_connadd_req { 12717f09a7e4ec5dd6a0d96498da6bf78762fba4468Szymon Janc int ctrl_sock; /* Connected control socket */ 12817f09a7e4ec5dd6a0d96498da6bf78762fba4468Szymon Janc int intr_sock; /* Connected interrupt socket */ 129e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u16 parser; 130e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u16 rd_size; 131e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann compat_uptr_t rd_data; 132e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u8 country; 133e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u8 subclass; 134e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u16 vendor; 135e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u16 product; 136e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u16 version; 137e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u32 flags; 138e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann __u32 idle_to; 139e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann char name[128]; 140e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann}; 141e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 142e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmannstatic int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 143e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann{ 144e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann if (cmd == HIDPGETCONNLIST) { 145e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann struct hidp_connlist_req cl; 146816a11d5ced501d368fabe09172f3d62744e8b53Johan Hedberg u32 uci; 147e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann int err; 148e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 149816a11d5ced501d368fabe09172f3d62744e8b53Johan Hedberg if (get_user(cl.cnum, (u32 __user *) arg) || 150e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann get_user(uci, (u32 __user *) (arg + 4))) 151e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann return -EFAULT; 152e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 153e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann cl.ci = compat_ptr(uci); 154e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 155e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann if (cl.cnum <= 0) 156e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann return -EINVAL; 157e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 158e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann err = hidp_get_connlist(&cl); 159e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 160816a11d5ced501d368fabe09172f3d62744e8b53Johan Hedberg if (!err && put_user(cl.cnum, (u32 __user *) arg)) 161e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann err = -EFAULT; 162e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 163e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann return err; 164e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann } else if (cmd == HIDPCONNADD) { 165e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann struct compat_hidp_connadd_req ca; 166e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann struct hidp_connadd_req __user *uca; 167e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 168e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann uca = compat_alloc_user_space(sizeof(*uca)); 169e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 17055e747445beec8df1133bb8681c884500546775cAl Viro if (copy_from_user(&ca, (void __user *) arg, sizeof(ca))) 171e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann return -EFAULT; 172e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 173e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann if (put_user(ca.ctrl_sock, &uca->ctrl_sock) || 174e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.intr_sock, &uca->intr_sock) || 175e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.parser, &uca->parser) || 176a83d6c0de8811d7bcc4eb67ed199d1120ca6cad8Marcel Holtmann put_user(ca.rd_size, &uca->rd_size) || 177e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(compat_ptr(ca.rd_data), &uca->rd_data) || 178e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.country, &uca->country) || 179e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.subclass, &uca->subclass) || 180e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.vendor, &uca->vendor) || 181e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.product, &uca->product) || 182e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.version, &uca->version) || 183e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.flags, &uca->flags) || 184e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann put_user(ca.idle_to, &uca->idle_to) || 185e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann copy_to_user(&uca->name[0], &ca.name[0], 128)) 186e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann return -EFAULT; 1878e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 188e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann arg = (unsigned long) uca; 189e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 190e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann /* Fall through. We don't actually write back any _changes_ 191e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann to the structure anyway, so there's no need to copy back 192e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann into the original compat version */ 193e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann } 194e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 195e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann return hidp_sock_ioctl(sock, cmd, arg); 196e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann} 197e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann#endif 198e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann 19990ddc4f0470427df306f308ad03db6b6b21644b8Eric Dumazetstatic const struct proto_ops hidp_sock_ops = { 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .family = PF_BLUETOOTH, 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = hidp_sock_release, 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = hidp_sock_ioctl, 204e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann#ifdef CONFIG_COMPAT 205e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann .compat_ioctl = hidp_sock_compat_ioctl, 206e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann#endif 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bind = sock_no_bind, 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getname = sock_no_getname, 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sendmsg = sock_no_sendmsg, 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .recvmsg = sock_no_recvmsg, 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .poll = sock_no_poll, 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .listen = sock_no_listen, 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .shutdown = sock_no_shutdown, 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .setsockopt = sock_no_setsockopt, 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getsockopt = sock_no_getsockopt, 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .connect = sock_no_connect, 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .socketpair = sock_no_socketpair, 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .accept = sock_no_accept, 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mmap = sock_no_mmap 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct proto hidp_proto = { 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "HIDP", 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .obj_size = sizeof(struct bt_sock) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2283f378b684453f2a028eda463ce383370545d9cc9Eric Parisstatic int hidp_sock_create(struct net *net, struct socket *sock, int protocol, 2293f378b684453f2a028eda463ce383370545d9cc9Eric Paris int kern) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sock %p", sock); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sock->type != SOCK_RAW) 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ESOCKTNOSUPPORT; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2386257ff2177ff02d7f260a7a501876aa41cb9a9f6Pavel Emelyanov sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sk) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_init_data(sock, sk); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock->ops = &hidp_sock_ops; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock->state = SS_UNCONNECTED; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_reset_flag(sk, SOCK_ZAPPED); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_protocol = protocol; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_state = BT_OPEN; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2535c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO bt_sock_link(&hidp_sk_list, sk); 2545c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 258ec1b4cf74c81bfd0fbe5bf62bafc86c45917e72fStephen Hemmingerstatic const struct net_proto_family hidp_sock_family_ops = { 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .family = PF_BLUETOOTH, 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .create = hidp_sock_create 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init hidp_init_sockets(void) 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = proto_register(&hidp_proto, 0); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err < 0) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); 2735c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO if (err < 0) { 2745c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO BT_ERR("Can't register HIDP socket"); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 2765c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO } 2775c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO 278b03166152f6da91cec8b66837b309dd3923ea536Al Viro err = bt_procfs_init(&init_net, "hidp", &hidp_sk_list, NULL); 2795c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO if (err < 0) { 2805c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO BT_ERR("Failed to create HIDP proc file"); 2815c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO bt_sock_unregister(BTPROTO_HIDP); 2825c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO goto error; 2835c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO } 2845c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO 2855c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO BT_INFO("HIDP socket layer initialized"); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror: 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds proto_unregister(&hidp_proto); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __exit hidp_cleanup_sockets(void) 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2965c6ad8eee0a8c5fb4ba8b741008490da9eb66af6Masatake YAMATO bt_procfs_cleanup(&init_net, "hidp"); 2975e9d7f868f04106139a58212b860dcdc268ad3afDavid Herrmann bt_sock_unregister(BTPROTO_HIDP); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds proto_unregister(&hidp_proto); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 300