blob: da4f54515775adf2a4681c7884f8894ec6f3be25 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 RFCOMM implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
4 Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation;
9
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090014 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090019 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 SOFTWARE IS DISCLAIMED.
22*/
23
24/*
25 * RFCOMM TTY.
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29
30#include <linux/tty.h>
31#include <linux/tty_driver.h>
32#include <linux/tty_flip.h>
33
Randy Dunlap4fc268d2006-01-11 12:17:47 -080034#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/slab.h>
36#include <linux/skbuff.h>
David Herrmann96af7392011-10-24 15:30:58 +020037#include <linux/workqueue.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
39#include <net/bluetooth/bluetooth.h>
Marcel Holtmann0a85b962006-07-06 13:09:02 +020040#include <net/bluetooth/hci_core.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <net/bluetooth/rfcomm.h>
42
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#define RFCOMM_TTY_MAGIC 0x6d02 /* magic number for rfcomm struct */
44#define RFCOMM_TTY_PORTS RFCOMM_MAX_DEV /* whole lotta rfcomm devices */
45#define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */
46#define RFCOMM_TTY_MINOR 0
47
48static struct tty_driver *rfcomm_tty_driver;
49
50struct rfcomm_dev {
Jiri Slabyf60db8c2012-04-02 13:54:50 +020051 struct tty_port port;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 struct list_head list;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54 char name[12];
55 int id;
56 unsigned long flags;
Marcel Holtmann9a5df922008-11-30 12:17:29 +010057 atomic_t opened;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 int err;
59
60 bdaddr_t src;
61 bdaddr_t dst;
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +020062 u8 channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +020064 uint modem_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
66 struct rfcomm_dlc *dlc;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 wait_queue_head_t wait;
David Herrmann96af7392011-10-24 15:30:58 +020068 struct work_struct wakeup_task;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
Marcel Holtmannc1a33132007-02-17 23:58:57 +010070 struct device *tty_dev;
71
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +020072 atomic_t wmem_alloc;
Marcel Holtmanna0c22f22008-07-14 20:13:52 +020073
74 struct sk_buff_head pending;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075};
76
77static LIST_HEAD(rfcomm_dev_list);
Gustavo F. Padovan393432c2011-12-27 15:28:45 -020078static DEFINE_SPINLOCK(rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb);
81static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err);
82static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
83
David Herrmann96af7392011-10-24 15:30:58 +020084static void rfcomm_tty_wakeup(struct work_struct *work);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86/* ---- Device functions ---- */
Jiri Slaby67054012012-04-02 13:54:51 +020087
88/*
89 * The reason this isn't actually a race, as you no doubt have a little voice
90 * screaming at you in your head, is that the refcount should never actually
91 * reach zero unless the device has already been taken off the list, in
92 * rfcomm_dev_del(). And if that's not true, we'll hit the BUG() in
93 * rfcomm_dev_destruct() anyway.
94 */
95static void rfcomm_dev_destruct(struct tty_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096{
Jiri Slaby67054012012-04-02 13:54:51 +020097 struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 struct rfcomm_dlc *dlc = dev->dlc;
99
100 BT_DBG("dev %p dlc %p", dev, dlc);
101
Dave Youngf9513752008-01-10 22:22:52 -0800102 /* Refcount should only hit zero when called from rfcomm_dev_del()
103 which will have taken us off the list. Everything else are
104 refcounting bugs. */
105 BUG_ON(!list_empty(&dev->list));
Ville Tervo8de0a152007-07-11 09:23:41 +0200106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 rfcomm_dlc_lock(dlc);
108 /* Detach DLC if it's owned by this dev */
109 if (dlc->owner == dev)
110 dlc->owner = NULL;
111 rfcomm_dlc_unlock(dlc);
112
113 rfcomm_dlc_put(dlc);
114
115 tty_unregister_device(rfcomm_tty_driver, dev->id);
116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 kfree(dev);
118
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900119 /* It's safe to call module_put() here because socket still
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 holds reference to this module. */
121 module_put(THIS_MODULE);
122}
123
Jiri Slaby67054012012-04-02 13:54:51 +0200124static const struct tty_port_operations rfcomm_port_ops = {
125 .destruct = rfcomm_dev_destruct,
126};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128static struct rfcomm_dev *__rfcomm_dev_get(int id)
129{
130 struct rfcomm_dev *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200132 list_for_each_entry(dev, &rfcomm_dev_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 if (dev->id == id)
134 return dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
136 return NULL;
137}
138
139static inline struct rfcomm_dev *rfcomm_dev_get(int id)
140{
141 struct rfcomm_dev *dev;
142
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200143 spin_lock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
145 dev = __rfcomm_dev_get(id);
Ville Tervo8de0a152007-07-11 09:23:41 +0200146
147 if (dev) {
148 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
149 dev = NULL;
150 else
Jiri Slaby67054012012-04-02 13:54:51 +0200151 tty_port_get(&dev->port);
Ville Tervo8de0a152007-07-11 09:23:41 +0200152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200154 spin_unlock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
156 return dev;
157}
158
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200159static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
160{
161 struct hci_dev *hdev;
162 struct hci_conn *conn;
163
164 hdev = hci_get_route(&dev->dst, &dev->src);
165 if (!hdev)
166 return NULL;
167
168 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200169
170 hci_dev_put(hdev);
171
Marcel Holtmannb2cfcd72006-10-15 17:31:05 +0200172 return conn ? &conn->dev : NULL;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200173}
174
Marcel Holtmanndae6a0f2007-10-20 14:52:38 +0200175static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
176{
177 struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
Gustavo F. Padovand6b2eb22010-09-03 18:29:46 -0300178 return sprintf(buf, "%s\n", batostr(&dev->dst));
Marcel Holtmanndae6a0f2007-10-20 14:52:38 +0200179}
180
181static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf)
182{
183 struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
184 return sprintf(buf, "%d\n", dev->channel);
185}
186
187static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
188static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL);
189
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
191{
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200192 struct rfcomm_dev *dev, *entry;
Luiz Augusto von Dentze57d7582012-03-07 20:20:14 +0200193 struct list_head *head = &rfcomm_dev_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 int err = 0;
195
196 BT_DBG("id %d channel %d", req->dev_id, req->channel);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900197
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200198 dev = kzalloc(sizeof(struct rfcomm_dev), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 if (!dev)
200 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200202 spin_lock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204 if (req->dev_id < 0) {
205 dev->id = 0;
206
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200207 list_for_each_entry(entry, &rfcomm_dev_list, list) {
208 if (entry->id != dev->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 break;
210
211 dev->id++;
Luiz Augusto von Dentze57d7582012-03-07 20:20:14 +0200212 head = &entry->list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 }
214 } else {
215 dev->id = req->dev_id;
216
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200217 list_for_each_entry(entry, &rfcomm_dev_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 if (entry->id == dev->id) {
219 err = -EADDRINUSE;
220 goto out;
221 }
222
223 if (entry->id > dev->id - 1)
224 break;
225
Luiz Augusto von Dentze57d7582012-03-07 20:20:14 +0200226 head = &entry->list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 }
228 }
229
230 if ((dev->id < 0) || (dev->id > RFCOMM_MAX_DEV - 1)) {
231 err = -ENFILE;
232 goto out;
233 }
234
235 sprintf(dev->name, "rfcomm%d", dev->id);
236
237 list_add(&dev->list, head);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
239 bacpy(&dev->src, &req->src);
240 bacpy(&dev->dst, &req->dst);
241 dev->channel = req->channel;
242
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900243 dev->flags = req->flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 ((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
245
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100246 atomic_set(&dev->opened, 0);
247
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200248 tty_port_init(&dev->port);
Jiri Slaby67054012012-04-02 13:54:51 +0200249 dev->port.ops = &rfcomm_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 init_waitqueue_head(&dev->wait);
David Herrmann96af7392011-10-24 15:30:58 +0200251 INIT_WORK(&dev->wakeup_task, rfcomm_tty_wakeup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200253 skb_queue_head_init(&dev->pending);
254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 rfcomm_dlc_lock(dlc);
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200256
257 if (req->flags & (1 << RFCOMM_REUSE_DLC)) {
258 struct sock *sk = dlc->owner;
259 struct sk_buff *skb;
260
261 BUG_ON(!sk);
262
263 rfcomm_dlc_throttle(dlc);
264
265 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
266 skb_orphan(skb);
267 skb_queue_tail(&dev->pending, skb);
268 atomic_sub(skb->len, &sk->sk_rmem_alloc);
269 }
270 }
271
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 dlc->data_ready = rfcomm_dev_data_ready;
273 dlc->state_change = rfcomm_dev_state_change;
274 dlc->modem_status = rfcomm_dev_modem_status;
275
276 dlc->owner = dev;
277 dev->dlc = dlc;
Marcel Holtmann8b6b3da2008-07-14 20:13:52 +0200278
279 rfcomm_dev_modem_status(dlc, dlc->remote_v24_sig);
280
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 rfcomm_dlc_unlock(dlc);
282
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900283 /* It's safe to call __module_get() here because socket already
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 holds reference to this module. */
285 __module_get(THIS_MODULE);
286
287out:
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200288 spin_unlock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Ilpo Järvinen037322a2008-12-14 23:18:00 -0800290 if (err < 0)
291 goto free;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100293 dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
Ville Tervo8de0a152007-07-11 09:23:41 +0200295 if (IS_ERR(dev->tty_dev)) {
Marcel Holtmann09c7d822007-07-26 00:12:25 -0700296 err = PTR_ERR(dev->tty_dev);
Ville Tervo8de0a152007-07-11 09:23:41 +0200297 list_del(&dev->list);
Ilpo Järvinen037322a2008-12-14 23:18:00 -0800298 goto free;
Ville Tervo8de0a152007-07-11 09:23:41 +0200299 }
300
Marcel Holtmanndae6a0f2007-10-20 14:52:38 +0200301 dev_set_drvdata(dev->tty_dev, dev);
302
303 if (device_create_file(dev->tty_dev, &dev_attr_address) < 0)
304 BT_ERR("Failed to create address attribute");
305
306 if (device_create_file(dev->tty_dev, &dev_attr_channel) < 0)
307 BT_ERR("Failed to create channel attribute");
308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 return dev->id;
Ilpo Järvinen037322a2008-12-14 23:18:00 -0800310
311free:
312 kfree(dev);
313 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314}
315
316static void rfcomm_dev_del(struct rfcomm_dev *dev)
317{
318 BT_DBG("dev %p", dev);
319
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100320 BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags));
321
322 if (atomic_read(&dev->opened) > 0)
323 return;
Dave Youngf9513752008-01-10 22:22:52 -0800324
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200325 spin_lock(&rfcomm_dev_lock);
Dave Youngf9513752008-01-10 22:22:52 -0800326 list_del_init(&dev->list);
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200327 spin_unlock(&rfcomm_dev_lock);
Dave Youngf9513752008-01-10 22:22:52 -0800328
Jiri Slaby67054012012-04-02 13:54:51 +0200329 tty_port_put(&dev->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330}
331
332/* ---- Send buffer ---- */
333static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
334{
335 /* We can't let it be zero, because we don't get a callback
336 when tx_credits becomes nonzero, hence we'd never wake up */
337 return dlc->mtu * (dlc->tx_credits?:1);
338}
339
340static void rfcomm_wfree(struct sk_buff *skb)
341{
342 struct rfcomm_dev *dev = (void *) skb->sk;
343 atomic_sub(skb->truesize, &dev->wmem_alloc);
344 if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags))
David Herrmann96af7392011-10-24 15:30:58 +0200345 queue_work(system_nrt_wq, &dev->wakeup_task);
Jiri Slaby67054012012-04-02 13:54:51 +0200346 tty_port_put(&dev->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347}
348
349static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
350{
Jiri Slaby67054012012-04-02 13:54:51 +0200351 tty_port_get(&dev->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 atomic_add(skb->truesize, &dev->wmem_alloc);
353 skb->sk = (void *) dev;
354 skb->destructor = rfcomm_wfree;
355}
356
Al Virodd0fc662005-10-07 07:46:04 +0100357static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358{
359 if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) {
360 struct sk_buff *skb = alloc_skb(size, priority);
361 if (skb) {
362 rfcomm_set_owner_w(skb, dev);
363 return skb;
364 }
365 }
366 return NULL;
367}
368
369/* ---- Device IOCTLs ---- */
370
371#define NOCAP_FLAGS ((1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP))
372
373static int rfcomm_create_dev(struct sock *sk, void __user *arg)
374{
375 struct rfcomm_dev_req req;
376 struct rfcomm_dlc *dlc;
377 int id;
378
379 if (copy_from_user(&req, arg, sizeof(req)))
380 return -EFAULT;
381
Ville Tervo8de0a152007-07-11 09:23:41 +0200382 BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
384 if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
385 return -EPERM;
386
387 if (req.flags & (1 << RFCOMM_REUSE_DLC)) {
388 /* Socket must be connected */
389 if (sk->sk_state != BT_CONNECTED)
390 return -EBADFD;
391
392 dlc = rfcomm_pi(sk)->dlc;
393 rfcomm_dlc_hold(dlc);
394 } else {
395 dlc = rfcomm_dlc_alloc(GFP_KERNEL);
396 if (!dlc)
397 return -ENOMEM;
398 }
399
400 id = rfcomm_dev_add(&req, dlc);
401 if (id < 0) {
402 rfcomm_dlc_put(dlc);
403 return id;
404 }
405
406 if (req.flags & (1 << RFCOMM_REUSE_DLC)) {
407 /* DLC is now used by device.
408 * Socket must be disconnected */
409 sk->sk_state = BT_CLOSED;
410 }
411
412 return id;
413}
414
415static int rfcomm_release_dev(void __user *arg)
416{
417 struct rfcomm_dev_req req;
418 struct rfcomm_dev *dev;
419
420 if (copy_from_user(&req, arg, sizeof(req)))
421 return -EFAULT;
422
Ville Tervo8de0a152007-07-11 09:23:41 +0200423 BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200425 dev = rfcomm_dev_get(req.dev_id);
426 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 return -ENODEV;
428
429 if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) {
Jiri Slaby67054012012-04-02 13:54:51 +0200430 tty_port_put(&dev->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 return -EPERM;
432 }
433
434 if (req.flags & (1 << RFCOMM_HANGUP_NOW))
435 rfcomm_dlc_close(dev->dlc, 0);
436
Mikko Rapeli84950cf2007-07-11 09:18:15 +0200437 /* Shut down TTY synchronously before freeing rfcomm_dev */
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200438 if (dev->port.tty)
439 tty_vhangup(dev->port.tty);
Mikko Rapeli84950cf2007-07-11 09:18:15 +0200440
Dave Young93d80742008-02-05 03:12:06 -0800441 if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
442 rfcomm_dev_del(dev);
Jiri Slaby67054012012-04-02 13:54:51 +0200443 tty_port_put(&dev->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 return 0;
445}
446
447static int rfcomm_get_dev_list(void __user *arg)
448{
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200449 struct rfcomm_dev *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 struct rfcomm_dev_list_req *dl;
451 struct rfcomm_dev_info *di;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 int n = 0, size, err;
453 u16 dev_num;
454
455 BT_DBG("");
456
457 if (get_user(dev_num, (u16 __user *) arg))
458 return -EFAULT;
459
460 if (!dev_num || dev_num > (PAGE_SIZE * 4) / sizeof(*di))
461 return -EINVAL;
462
463 size = sizeof(*dl) + dev_num * sizeof(*di);
464
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200465 dl = kmalloc(size, GFP_KERNEL);
466 if (!dl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 return -ENOMEM;
468
469 di = dl->dev_info;
470
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200471 spin_lock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200473 list_for_each_entry(dev, &rfcomm_dev_list, list) {
Ville Tervo8de0a152007-07-11 09:23:41 +0200474 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
475 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 (di + n)->id = dev->id;
477 (di + n)->flags = dev->flags;
478 (di + n)->state = dev->dlc->state;
479 (di + n)->channel = dev->channel;
480 bacpy(&(di + n)->src, &dev->src);
481 bacpy(&(di + n)->dst, &dev->dst);
482 if (++n >= dev_num)
483 break;
484 }
485
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200486 spin_unlock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 dl->dev_num = n;
489 size = sizeof(*dl) + n * sizeof(*di);
490
491 err = copy_to_user(arg, dl, size);
492 kfree(dl);
493
494 return err ? -EFAULT : 0;
495}
496
497static int rfcomm_get_dev_info(void __user *arg)
498{
499 struct rfcomm_dev *dev;
500 struct rfcomm_dev_info di;
501 int err = 0;
502
503 BT_DBG("");
504
505 if (copy_from_user(&di, arg, sizeof(di)))
506 return -EFAULT;
507
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200508 dev = rfcomm_dev_get(di.id);
509 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 return -ENODEV;
511
512 di.flags = dev->flags;
513 di.channel = dev->channel;
514 di.state = dev->dlc->state;
515 bacpy(&di.src, &dev->src);
516 bacpy(&di.dst, &dev->dst);
517
518 if (copy_to_user(arg, &di, sizeof(di)))
519 err = -EFAULT;
520
Jiri Slaby67054012012-04-02 13:54:51 +0200521 tty_port_put(&dev->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 return err;
523}
524
525int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
526{
527 BT_DBG("cmd %d arg %p", cmd, arg);
528
529 switch (cmd) {
530 case RFCOMMCREATEDEV:
531 return rfcomm_create_dev(sk, arg);
532
533 case RFCOMMRELEASEDEV:
534 return rfcomm_release_dev(arg);
535
536 case RFCOMMGETDEVLIST:
537 return rfcomm_get_dev_list(arg);
538
539 case RFCOMMGETDEVINFO:
540 return rfcomm_get_dev_info(arg);
541 }
542
543 return -EINVAL;
544}
545
546/* ---- DLC callbacks ---- */
547static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
548{
549 struct rfcomm_dev *dev = dlc->owner;
550 struct tty_struct *tty;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900551
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200552 if (!dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 kfree_skb(skb);
554 return;
555 }
556
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200557 tty = dev->port.tty;
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200558 if (!tty || !skb_queue_empty(&dev->pending)) {
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200559 skb_queue_tail(&dev->pending, skb);
560 return;
561 }
562
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);
564
Paul Fulghum817d6d32006-06-28 04:26:47 -0700565 tty_insert_flip_string(tty, skb->data, skb->len);
566 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568 kfree_skb(skb);
569}
570
571static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
572{
573 struct rfcomm_dev *dev = dlc->owner;
574 if (!dev)
575 return;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900576
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
578
579 dev->err = err;
580 wake_up_interruptible(&dev->wait);
581
582 if (dlc->state == BT_CLOSED) {
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200583 if (!dev->port.tty) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
Dave Young537d59a2008-06-01 23:50:52 -0700585 /* Drop DLC lock here to avoid deadlock
586 * 1. rfcomm_dev_get will take rfcomm_dev_lock
587 * but in rfcomm_dev_add there's lock order:
588 * rfcomm_dev_lock -> dlc lock
Jiri Slaby67054012012-04-02 13:54:51 +0200589 * 2. tty_port_put will deadlock if it's
Dave Young537d59a2008-06-01 23:50:52 -0700590 * the last reference
591 */
592 rfcomm_dlc_unlock(dlc);
593 if (rfcomm_dev_get(dev->id) == NULL) {
594 rfcomm_dlc_lock(dlc);
Marcel Holtmann77f2a452007-05-05 00:36:10 +0200595 return;
Dave Young537d59a2008-06-01 23:50:52 -0700596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
Marcel Holtmann77f2a452007-05-05 00:36:10 +0200598 rfcomm_dev_del(dev);
Jiri Slaby67054012012-04-02 13:54:51 +0200599 tty_port_put(&dev->port);
Dave Young537d59a2008-06-01 23:50:52 -0700600 rfcomm_dlc_lock(dlc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900602 } else
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200603 tty_hangup(dev->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 }
605}
606
607static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
608{
609 struct rfcomm_dev *dev = dlc->owner;
610 if (!dev)
611 return;
Timo Teräs7b9eb9e2005-08-09 20:28:21 -0700612
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig);
614
Timo Teräs7b9eb9e2005-08-09 20:28:21 -0700615 if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) {
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200616 if (dev->port.tty && !C_CLOCAL(dev->port.tty))
617 tty_hangup(dev->port.tty);
Timo Teräs7b9eb9e2005-08-09 20:28:21 -0700618 }
619
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900620 dev->modem_status =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 ((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) |
622 ((v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0) |
623 ((v24_sig & RFCOMM_V24_IC) ? TIOCM_RI : 0) |
624 ((v24_sig & RFCOMM_V24_DV) ? TIOCM_CD : 0);
625}
626
627/* ---- TTY functions ---- */
David Herrmann96af7392011-10-24 15:30:58 +0200628static void rfcomm_tty_wakeup(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629{
David Herrmann96af7392011-10-24 15:30:58 +0200630 struct rfcomm_dev *dev = container_of(work, struct rfcomm_dev,
631 wakeup_task);
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200632 struct tty_struct *tty = dev->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 if (!tty)
634 return;
635
636 BT_DBG("dev %p tty %p", dev, tty);
Alan Coxa352def2008-07-16 21:53:12 +0100637 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638}
639
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200640static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
641{
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200642 struct tty_struct *tty = dev->port.tty;
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200643 struct sk_buff *skb;
644 int inserted = 0;
645
646 if (!tty)
647 return;
648
649 BT_DBG("dev %p tty %p", dev, tty);
650
651 rfcomm_dlc_lock(dev->dlc);
652
653 while ((skb = skb_dequeue(&dev->pending))) {
654 inserted += tty_insert_flip_string(tty, skb->data, skb->len);
655 kfree_skb(skb);
656 }
657
658 rfcomm_dlc_unlock(dev->dlc);
659
660 if (inserted > 0)
661 tty_flip_buffer_push(tty);
662}
663
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
665{
666 DECLARE_WAITQUEUE(wait, current);
667 struct rfcomm_dev *dev;
668 struct rfcomm_dlc *dlc;
669 int err, id;
670
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900671 id = tty->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
673 BT_DBG("tty %p id %d", tty, id);
674
675 /* We don't leak this refcount. For reasons which are not entirely
676 clear, the TTY layer will call our ->close() method even if the
677 open fails. We decrease the refcount there, and decreasing it
678 here too would cause breakage. */
679 dev = rfcomm_dev_get(id);
680 if (!dev)
681 return -ENODEV;
682
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100683 BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
684 dev->channel, atomic_read(&dev->opened));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100686 if (atomic_inc_return(&dev->opened) > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 return 0;
688
689 dlc = dev->dlc;
690
691 /* Attach TTY and open DLC */
692
693 rfcomm_dlc_lock(dlc);
694 tty->driver_data = dev;
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200695 dev->port.tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 rfcomm_dlc_unlock(dlc);
697 set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
698
699 err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);
700 if (err < 0)
701 return err;
702
703 /* Wait for DLC to connect */
704 add_wait_queue(&dev->wait, &wait);
705 while (1) {
706 set_current_state(TASK_INTERRUPTIBLE);
707
708 if (dlc->state == BT_CLOSED) {
709 err = -dev->err;
710 break;
711 }
712
713 if (dlc->state == BT_CONNECTED)
714 break;
715
716 if (signal_pending(current)) {
717 err = -EINTR;
718 break;
719 }
720
Vladislav P840af822011-02-14 15:21:50 -0200721 tty_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 schedule();
Vladislav P840af822011-02-14 15:21:50 -0200723 tty_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 }
725 set_current_state(TASK_RUNNING);
726 remove_wait_queue(&dev->wait, &wait);
727
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100728 if (err == 0)
Cornelia Huckffa6a702009-03-04 12:44:00 +0100729 device_move(dev->tty_dev, rfcomm_get_device(dev),
730 DPM_ORDER_DEV_AFTER_PARENT);
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100731
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200732 rfcomm_tty_copy_pending(dev);
733
734 rfcomm_dlc_unthrottle(dev->dlc);
735
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 return err;
737}
738
739static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
740{
741 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
742 if (!dev)
743 return;
744
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100745 BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
746 atomic_read(&dev->opened));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100748 if (atomic_dec_and_test(&dev->opened)) {
Dave Youngacea6852008-01-21 22:35:21 -0800749 if (dev->tty_dev->parent)
Cornelia Huckffa6a702009-03-04 12:44:00 +0100750 device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 /* Close DLC and dettach TTY */
753 rfcomm_dlc_close(dev->dlc, 0);
754
755 clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
David Herrmann96af7392011-10-24 15:30:58 +0200756 cancel_work_sync(&dev->wakeup_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
758 rfcomm_dlc_lock(dev->dlc);
759 tty->driver_data = NULL;
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200760 dev->port.tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 rfcomm_dlc_unlock(dev->dlc);
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100762
763 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200764 spin_lock(&rfcomm_dev_lock);
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100765 list_del_init(&dev->list);
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200766 spin_unlock(&rfcomm_dev_lock);
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100767
Jiri Slaby67054012012-04-02 13:54:51 +0200768 tty_port_put(&dev->port);
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100769 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 }
771
Jiri Slaby67054012012-04-02 13:54:51 +0200772 tty_port_put(&dev->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773}
774
775static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
776{
777 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
778 struct rfcomm_dlc *dlc = dev->dlc;
779 struct sk_buff *skb;
780 int err = 0, sent = 0, size;
781
782 BT_DBG("tty %p count %d", tty, count);
783
784 while (count) {
785 size = min_t(uint, count, dlc->mtu);
786
787 skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900788
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 if (!skb)
790 break;
791
792 skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
793
794 memcpy(skb_put(skb, size), buf + sent, size);
795
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200796 err = rfcomm_dlc_send(dlc, skb);
797 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 kfree_skb(skb);
799 break;
800 }
801
802 sent += size;
803 count -= size;
804 }
805
806 return sent ? sent : err;
807}
808
809static int rfcomm_tty_write_room(struct tty_struct *tty)
810{
811 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
812 int room;
813
814 BT_DBG("tty %p", tty);
815
Marcel Holtmannb6e557f2007-01-08 02:16:27 +0100816 if (!dev || !dev->dlc)
817 return 0;
818
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc);
820 if (room < 0)
821 room = 0;
Marcel Holtmannb6e557f2007-01-08 02:16:27 +0100822
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 return room;
824}
825
Alan Cox6caa76b2011-02-14 16:27:22 +0000826static int rfcomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
828 BT_DBG("tty %p cmd 0x%02x", tty, cmd);
829
830 switch (cmd) {
831 case TCGETS:
832 BT_DBG("TCGETS is not supported");
833 return -ENOIOCTLCMD;
834
835 case TCSETS:
836 BT_DBG("TCSETS is not supported");
837 return -ENOIOCTLCMD;
838
839 case TIOCMIWAIT:
840 BT_DBG("TIOCMIWAIT");
841 break;
842
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 case TIOCGSERIAL:
844 BT_ERR("TIOCGSERIAL is not supported");
845 return -ENOIOCTLCMD;
846
847 case TIOCSSERIAL:
848 BT_ERR("TIOCSSERIAL is not supported");
849 return -ENOIOCTLCMD;
850
851 case TIOCSERGSTRUCT:
852 BT_ERR("TIOCSERGSTRUCT is not supported");
853 return -ENOIOCTLCMD;
854
855 case TIOCSERGETLSR:
856 BT_ERR("TIOCSERGETLSR is not supported");
857 return -ENOIOCTLCMD;
858
859 case TIOCSERCONFIG:
860 BT_ERR("TIOCSERCONFIG is not supported");
861 return -ENOIOCTLCMD;
862
863 default:
864 return -ENOIOCTLCMD; /* ioctls which we must ignore */
865
866 }
867
868 return -ENOIOCTLCMD;
869}
870
Alan Cox606d0992006-12-08 02:38:45 -0800871static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872{
Alan Cox606d0992006-12-08 02:38:45 -0800873 struct ktermios *new = tty->termios;
J. Suter3a5e9032005-08-09 20:28:46 -0700874 int old_baud_rate = tty_termios_baud_rate(old);
875 int new_baud_rate = tty_termios_baud_rate(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
J. Suter3a5e9032005-08-09 20:28:46 -0700877 u8 baud, data_bits, stop_bits, parity, x_on, x_off;
878 u16 changes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
J. Suter3a5e9032005-08-09 20:28:46 -0700880 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
881
882 BT_DBG("tty %p termios %p", tty, old);
883
Marcel Holtmannff2d3672006-11-18 22:14:42 +0100884 if (!dev || !dev->dlc || !dev->dlc->session)
Marcel Holtmanncb19d9e2006-10-15 17:31:10 +0200885 return;
886
J. Suter3a5e9032005-08-09 20:28:46 -0700887 /* Handle turning off CRTSCTS */
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900888 if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS))
J. Suter3a5e9032005-08-09 20:28:46 -0700889 BT_DBG("Turning off CRTSCTS unsupported");
890
891 /* Parity on/off and when on, odd/even */
892 if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) ||
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200893 ((old->c_cflag & PARODD) != (new->c_cflag & PARODD))) {
J. Suter3a5e9032005-08-09 20:28:46 -0700894 changes |= RFCOMM_RPN_PM_PARITY;
895 BT_DBG("Parity change detected.");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 }
J. Suter3a5e9032005-08-09 20:28:46 -0700897
898 /* Mark and space parity are not supported! */
899 if (new->c_cflag & PARENB) {
900 if (new->c_cflag & PARODD) {
901 BT_DBG("Parity is ODD");
902 parity = RFCOMM_RPN_PARITY_ODD;
903 } else {
904 BT_DBG("Parity is EVEN");
905 parity = RFCOMM_RPN_PARITY_EVEN;
906 }
907 } else {
908 BT_DBG("Parity is OFF");
909 parity = RFCOMM_RPN_PARITY_NONE;
910 }
911
912 /* Setting the x_on / x_off characters */
913 if (old->c_cc[VSTOP] != new->c_cc[VSTOP]) {
914 BT_DBG("XOFF custom");
915 x_on = new->c_cc[VSTOP];
916 changes |= RFCOMM_RPN_PM_XON;
917 } else {
918 BT_DBG("XOFF default");
919 x_on = RFCOMM_RPN_XON_CHAR;
920 }
921
922 if (old->c_cc[VSTART] != new->c_cc[VSTART]) {
923 BT_DBG("XON custom");
924 x_off = new->c_cc[VSTART];
925 changes |= RFCOMM_RPN_PM_XOFF;
926 } else {
927 BT_DBG("XON default");
928 x_off = RFCOMM_RPN_XOFF_CHAR;
929 }
930
931 /* Handle setting of stop bits */
932 if ((old->c_cflag & CSTOPB) != (new->c_cflag & CSTOPB))
933 changes |= RFCOMM_RPN_PM_STOP;
934
935 /* POSIX does not support 1.5 stop bits and RFCOMM does not
936 * support 2 stop bits. So a request for 2 stop bits gets
937 * translated to 1.5 stop bits */
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200938 if (new->c_cflag & CSTOPB)
J. Suter3a5e9032005-08-09 20:28:46 -0700939 stop_bits = RFCOMM_RPN_STOP_15;
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200940 else
J. Suter3a5e9032005-08-09 20:28:46 -0700941 stop_bits = RFCOMM_RPN_STOP_1;
J. Suter3a5e9032005-08-09 20:28:46 -0700942
943 /* Handle number of data bits [5-8] */
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900944 if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE))
J. Suter3a5e9032005-08-09 20:28:46 -0700945 changes |= RFCOMM_RPN_PM_DATA;
946
947 switch (new->c_cflag & CSIZE) {
948 case CS5:
949 data_bits = RFCOMM_RPN_DATA_5;
950 break;
951 case CS6:
952 data_bits = RFCOMM_RPN_DATA_6;
953 break;
954 case CS7:
955 data_bits = RFCOMM_RPN_DATA_7;
956 break;
957 case CS8:
958 data_bits = RFCOMM_RPN_DATA_8;
959 break;
960 default:
961 data_bits = RFCOMM_RPN_DATA_8;
962 break;
963 }
964
965 /* Handle baudrate settings */
966 if (old_baud_rate != new_baud_rate)
967 changes |= RFCOMM_RPN_PM_BITRATE;
968
969 switch (new_baud_rate) {
970 case 2400:
971 baud = RFCOMM_RPN_BR_2400;
972 break;
973 case 4800:
974 baud = RFCOMM_RPN_BR_4800;
975 break;
976 case 7200:
977 baud = RFCOMM_RPN_BR_7200;
978 break;
979 case 9600:
980 baud = RFCOMM_RPN_BR_9600;
981 break;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900982 case 19200:
J. Suter3a5e9032005-08-09 20:28:46 -0700983 baud = RFCOMM_RPN_BR_19200;
984 break;
985 case 38400:
986 baud = RFCOMM_RPN_BR_38400;
987 break;
988 case 57600:
989 baud = RFCOMM_RPN_BR_57600;
990 break;
991 case 115200:
992 baud = RFCOMM_RPN_BR_115200;
993 break;
994 case 230400:
995 baud = RFCOMM_RPN_BR_230400;
996 break;
997 default:
998 /* 9600 is standard accordinag to the RFCOMM specification */
999 baud = RFCOMM_RPN_BR_9600;
1000 break;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001001
J. Suter3a5e9032005-08-09 20:28:46 -07001002 }
1003
1004 if (changes)
1005 rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud,
1006 data_bits, stop_bits, parity,
1007 RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008}
1009
1010static void rfcomm_tty_throttle(struct tty_struct *tty)
1011{
1012 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1013
1014 BT_DBG("tty %p dev %p", tty, dev);
J. Suter3a5e9032005-08-09 20:28:46 -07001015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 rfcomm_dlc_throttle(dev->dlc);
1017}
1018
1019static void rfcomm_tty_unthrottle(struct tty_struct *tty)
1020{
1021 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1022
1023 BT_DBG("tty %p dev %p", tty, dev);
J. Suter3a5e9032005-08-09 20:28:46 -07001024
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 rfcomm_dlc_unthrottle(dev->dlc);
1026}
1027
1028static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty)
1029{
1030 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
1032 BT_DBG("tty %p dev %p", tty, dev);
1033
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001034 if (!dev || !dev->dlc)
1035 return 0;
1036
1037 if (!skb_queue_empty(&dev->dlc->tx_queue))
1038 return dev->dlc->mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
1040 return 0;
1041}
1042
1043static void rfcomm_tty_flush_buffer(struct tty_struct *tty)
1044{
1045 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 BT_DBG("tty %p dev %p", tty, dev);
1048
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001049 if (!dev || !dev->dlc)
1050 return;
1051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 skb_queue_purge(&dev->dlc->tx_queue);
Alan Coxa352def2008-07-16 21:53:12 +01001053 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054}
1055
1056static void rfcomm_tty_send_xchar(struct tty_struct *tty, char ch)
1057{
1058 BT_DBG("tty %p ch %c", tty, ch);
1059}
1060
1061static void rfcomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
1062{
1063 BT_DBG("tty %p timeout %d", tty, timeout);
1064}
1065
1066static void rfcomm_tty_hangup(struct tty_struct *tty)
1067{
1068 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 BT_DBG("tty %p dev %p", tty, dev);
1071
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001072 if (!dev)
1073 return;
1074
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 rfcomm_tty_flush_buffer(tty);
1076
Marcel Holtmann77f2a452007-05-05 00:36:10 +02001077 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
1078 if (rfcomm_dev_get(dev->id) == NULL)
1079 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 rfcomm_dev_del(dev);
Jiri Slaby67054012012-04-02 13:54:51 +02001081 tty_port_put(&dev->port);
Marcel Holtmann77f2a452007-05-05 00:36:10 +02001082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083}
1084
Alan Cox60b33c12011-02-14 16:26:14 +00001085static int rfcomm_tty_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086{
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001087 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
1089 BT_DBG("tty %p dev %p", tty, dev);
1090
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001091 return dev->modem_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092}
1093
Alan Cox20b9d172011-02-14 16:26:50 +00001094static int rfcomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
J. Suter3a5e9032005-08-09 20:28:46 -07001096 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1097 struct rfcomm_dlc *dlc = dev->dlc;
1098 u8 v24_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear);
1101
J. Suter3a5e9032005-08-09 20:28:46 -07001102 rfcomm_dlc_get_modem_status(dlc, &v24_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
J. Suter3a5e9032005-08-09 20:28:46 -07001104 if (set & TIOCM_DSR || set & TIOCM_DTR)
1105 v24_sig |= RFCOMM_V24_RTC;
1106 if (set & TIOCM_RTS || set & TIOCM_CTS)
1107 v24_sig |= RFCOMM_V24_RTR;
1108 if (set & TIOCM_RI)
1109 v24_sig |= RFCOMM_V24_IC;
1110 if (set & TIOCM_CD)
1111 v24_sig |= RFCOMM_V24_DV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
J. Suter3a5e9032005-08-09 20:28:46 -07001113 if (clear & TIOCM_DSR || clear & TIOCM_DTR)
1114 v24_sig &= ~RFCOMM_V24_RTC;
1115 if (clear & TIOCM_RTS || clear & TIOCM_CTS)
1116 v24_sig &= ~RFCOMM_V24_RTR;
1117 if (clear & TIOCM_RI)
1118 v24_sig &= ~RFCOMM_V24_IC;
1119 if (clear & TIOCM_CD)
1120 v24_sig &= ~RFCOMM_V24_DV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
J. Suter3a5e9032005-08-09 20:28:46 -07001122 rfcomm_dlc_set_modem_status(dlc, v24_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
J. Suter3a5e9032005-08-09 20:28:46 -07001124 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125}
1126
1127/* ---- TTY structure ---- */
1128
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001129static const struct tty_operations rfcomm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 .open = rfcomm_tty_open,
1131 .close = rfcomm_tty_close,
1132 .write = rfcomm_tty_write,
1133 .write_room = rfcomm_tty_write_room,
1134 .chars_in_buffer = rfcomm_tty_chars_in_buffer,
1135 .flush_buffer = rfcomm_tty_flush_buffer,
1136 .ioctl = rfcomm_tty_ioctl,
1137 .throttle = rfcomm_tty_throttle,
1138 .unthrottle = rfcomm_tty_unthrottle,
1139 .set_termios = rfcomm_tty_set_termios,
1140 .send_xchar = rfcomm_tty_send_xchar,
1141 .hangup = rfcomm_tty_hangup,
1142 .wait_until_sent = rfcomm_tty_wait_until_sent,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 .tiocmget = rfcomm_tty_tiocmget,
1144 .tiocmset = rfcomm_tty_tiocmset,
1145};
1146
Gustavo F. Padovan2f8362a2010-07-24 02:04:45 -03001147int __init rfcomm_init_ttys(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148{
David Herrmann5ada9912011-10-24 15:30:57 +02001149 int error;
1150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
1152 if (!rfcomm_tty_driver)
David Herrmann5ada9912011-10-24 15:30:57 +02001153 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 rfcomm_tty_driver->driver_name = "rfcomm";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 rfcomm_tty_driver->name = "rfcomm";
1157 rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR;
1158 rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR;
1159 rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1160 rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001161 rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 rfcomm_tty_driver->init_termios = tty_std_termios;
1163 rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Marcel Holtmannca37bdd2008-07-14 20:13:52 +02001164 rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
1166
David Herrmann5ada9912011-10-24 15:30:57 +02001167 error = tty_register_driver(rfcomm_tty_driver);
1168 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 BT_ERR("Can't register RFCOMM TTY driver");
1170 put_tty_driver(rfcomm_tty_driver);
David Herrmann5ada9912011-10-24 15:30:57 +02001171 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 }
1173
1174 BT_INFO("RFCOMM TTY layer initialized");
1175
1176 return 0;
1177}
1178
Gustavo F. Padovan28e95092010-07-31 19:57:05 -03001179void rfcomm_cleanup_ttys(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180{
1181 tty_unregister_driver(rfcomm_tty_driver);
1182 put_tty_driver(rfcomm_tty_driver);
1183}