blob: 97c2a087a9f1f4d9cd63ef9d2312fc31556cccea [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;
53 atomic_t refcnt;
54
55 char name[12];
56 int id;
57 unsigned long flags;
Marcel Holtmann9a5df922008-11-30 12:17:29 +010058 atomic_t opened;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 int err;
60
61 bdaddr_t src;
62 bdaddr_t dst;
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +020063 u8 channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +020065 uint modem_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67 struct rfcomm_dlc *dlc;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 wait_queue_head_t wait;
David Herrmann96af7392011-10-24 15:30:58 +020069 struct work_struct wakeup_task;
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Marcel Holtmannc1a33132007-02-17 23:58:57 +010071 struct device *tty_dev;
72
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +020073 atomic_t wmem_alloc;
Marcel Holtmanna0c22f22008-07-14 20:13:52 +020074
75 struct sk_buff_head pending;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076};
77
78static LIST_HEAD(rfcomm_dev_list);
Gustavo F. Padovan393432c2011-12-27 15:28:45 -020079static DEFINE_SPINLOCK(rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
81static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb);
82static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err);
83static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
84
David Herrmann96af7392011-10-24 15:30:58 +020085static void rfcomm_tty_wakeup(struct work_struct *work);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87/* ---- Device functions ---- */
88static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
89{
90 struct rfcomm_dlc *dlc = dev->dlc;
91
92 BT_DBG("dev %p dlc %p", dev, dlc);
93
Dave Youngf9513752008-01-10 22:22:52 -080094 /* Refcount should only hit zero when called from rfcomm_dev_del()
95 which will have taken us off the list. Everything else are
96 refcounting bugs. */
97 BUG_ON(!list_empty(&dev->list));
Ville Tervo8de0a152007-07-11 09:23:41 +020098
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 rfcomm_dlc_lock(dlc);
100 /* Detach DLC if it's owned by this dev */
101 if (dlc->owner == dev)
102 dlc->owner = NULL;
103 rfcomm_dlc_unlock(dlc);
104
105 rfcomm_dlc_put(dlc);
106
107 tty_unregister_device(rfcomm_tty_driver, dev->id);
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 kfree(dev);
110
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900111 /* It's safe to call module_put() here because socket still
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 holds reference to this module. */
113 module_put(THIS_MODULE);
114}
115
116static inline void rfcomm_dev_hold(struct rfcomm_dev *dev)
117{
118 atomic_inc(&dev->refcnt);
119}
120
121static inline void rfcomm_dev_put(struct rfcomm_dev *dev)
122{
123 /* The reason this isn't actually a race, as you no
124 doubt have a little voice screaming at you in your
125 head, is that the refcount should never actually
126 reach zero unless the device has already been taken
127 off the list, in rfcomm_dev_del(). And if that's not
128 true, we'll hit the BUG() in rfcomm_dev_destruct()
129 anyway. */
130 if (atomic_dec_and_test(&dev->refcnt))
131 rfcomm_dev_destruct(dev);
132}
133
134static struct rfcomm_dev *__rfcomm_dev_get(int id)
135{
136 struct rfcomm_dev *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200138 list_for_each_entry(dev, &rfcomm_dev_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 if (dev->id == id)
140 return dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
142 return NULL;
143}
144
145static inline struct rfcomm_dev *rfcomm_dev_get(int id)
146{
147 struct rfcomm_dev *dev;
148
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200149 spin_lock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
151 dev = __rfcomm_dev_get(id);
Ville Tervo8de0a152007-07-11 09:23:41 +0200152
153 if (dev) {
154 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
155 dev = NULL;
156 else
157 rfcomm_dev_hold(dev);
158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200160 spin_unlock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
162 return dev;
163}
164
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200165static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
166{
167 struct hci_dev *hdev;
168 struct hci_conn *conn;
169
170 hdev = hci_get_route(&dev->dst, &dev->src);
171 if (!hdev)
172 return NULL;
173
174 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200175
176 hci_dev_put(hdev);
177
Marcel Holtmannb2cfcd72006-10-15 17:31:05 +0200178 return conn ? &conn->dev : NULL;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200179}
180
Marcel Holtmanndae6a0f2007-10-20 14:52:38 +0200181static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
182{
183 struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
Gustavo F. Padovand6b2eb22010-09-03 18:29:46 -0300184 return sprintf(buf, "%s\n", batostr(&dev->dst));
Marcel Holtmanndae6a0f2007-10-20 14:52:38 +0200185}
186
187static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf)
188{
189 struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
190 return sprintf(buf, "%d\n", dev->channel);
191}
192
193static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
194static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL);
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
197{
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200198 struct rfcomm_dev *dev, *entry;
Luiz Augusto von Dentze57d7582012-03-07 20:20:14 +0200199 struct list_head *head = &rfcomm_dev_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 int err = 0;
201
202 BT_DBG("id %d channel %d", req->dev_id, req->channel);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900203
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200204 dev = kzalloc(sizeof(struct rfcomm_dev), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 if (!dev)
206 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200208 spin_lock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
210 if (req->dev_id < 0) {
211 dev->id = 0;
212
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200213 list_for_each_entry(entry, &rfcomm_dev_list, list) {
214 if (entry->id != dev->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 break;
216
217 dev->id++;
Luiz Augusto von Dentze57d7582012-03-07 20:20:14 +0200218 head = &entry->list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 }
220 } else {
221 dev->id = req->dev_id;
222
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200223 list_for_each_entry(entry, &rfcomm_dev_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 if (entry->id == dev->id) {
225 err = -EADDRINUSE;
226 goto out;
227 }
228
229 if (entry->id > dev->id - 1)
230 break;
231
Luiz Augusto von Dentze57d7582012-03-07 20:20:14 +0200232 head = &entry->list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 }
234 }
235
236 if ((dev->id < 0) || (dev->id > RFCOMM_MAX_DEV - 1)) {
237 err = -ENFILE;
238 goto out;
239 }
240
241 sprintf(dev->name, "rfcomm%d", dev->id);
242
243 list_add(&dev->list, head);
244 atomic_set(&dev->refcnt, 1);
245
246 bacpy(&dev->src, &req->src);
247 bacpy(&dev->dst, &req->dst);
248 dev->channel = req->channel;
249
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900250 dev->flags = req->flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 ((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
252
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100253 atomic_set(&dev->opened, 0);
254
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200255 tty_port_init(&dev->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 init_waitqueue_head(&dev->wait);
David Herrmann96af7392011-10-24 15:30:58 +0200257 INIT_WORK(&dev->wakeup_task, rfcomm_tty_wakeup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200259 skb_queue_head_init(&dev->pending);
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 rfcomm_dlc_lock(dlc);
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200262
263 if (req->flags & (1 << RFCOMM_REUSE_DLC)) {
264 struct sock *sk = dlc->owner;
265 struct sk_buff *skb;
266
267 BUG_ON(!sk);
268
269 rfcomm_dlc_throttle(dlc);
270
271 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
272 skb_orphan(skb);
273 skb_queue_tail(&dev->pending, skb);
274 atomic_sub(skb->len, &sk->sk_rmem_alloc);
275 }
276 }
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 dlc->data_ready = rfcomm_dev_data_ready;
279 dlc->state_change = rfcomm_dev_state_change;
280 dlc->modem_status = rfcomm_dev_modem_status;
281
282 dlc->owner = dev;
283 dev->dlc = dlc;
Marcel Holtmann8b6b3da2008-07-14 20:13:52 +0200284
285 rfcomm_dev_modem_status(dlc, dlc->remote_v24_sig);
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 rfcomm_dlc_unlock(dlc);
288
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900289 /* It's safe to call __module_get() here because socket already
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 holds reference to this module. */
291 __module_get(THIS_MODULE);
292
293out:
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200294 spin_unlock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
Ilpo Järvinen037322a2008-12-14 23:18:00 -0800296 if (err < 0)
297 goto free;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100299 dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
Ville Tervo8de0a152007-07-11 09:23:41 +0200301 if (IS_ERR(dev->tty_dev)) {
Marcel Holtmann09c7d822007-07-26 00:12:25 -0700302 err = PTR_ERR(dev->tty_dev);
Ville Tervo8de0a152007-07-11 09:23:41 +0200303 list_del(&dev->list);
Ilpo Järvinen037322a2008-12-14 23:18:00 -0800304 goto free;
Ville Tervo8de0a152007-07-11 09:23:41 +0200305 }
306
Marcel Holtmanndae6a0f2007-10-20 14:52:38 +0200307 dev_set_drvdata(dev->tty_dev, dev);
308
309 if (device_create_file(dev->tty_dev, &dev_attr_address) < 0)
310 BT_ERR("Failed to create address attribute");
311
312 if (device_create_file(dev->tty_dev, &dev_attr_channel) < 0)
313 BT_ERR("Failed to create channel attribute");
314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 return dev->id;
Ilpo Järvinen037322a2008-12-14 23:18:00 -0800316
317free:
318 kfree(dev);
319 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320}
321
322static void rfcomm_dev_del(struct rfcomm_dev *dev)
323{
324 BT_DBG("dev %p", dev);
325
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100326 BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags));
327
328 if (atomic_read(&dev->opened) > 0)
329 return;
Dave Youngf9513752008-01-10 22:22:52 -0800330
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200331 spin_lock(&rfcomm_dev_lock);
Dave Youngf9513752008-01-10 22:22:52 -0800332 list_del_init(&dev->list);
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200333 spin_unlock(&rfcomm_dev_lock);
Dave Youngf9513752008-01-10 22:22:52 -0800334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 rfcomm_dev_put(dev);
336}
337
338/* ---- Send buffer ---- */
339static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
340{
341 /* We can't let it be zero, because we don't get a callback
342 when tx_credits becomes nonzero, hence we'd never wake up */
343 return dlc->mtu * (dlc->tx_credits?:1);
344}
345
346static void rfcomm_wfree(struct sk_buff *skb)
347{
348 struct rfcomm_dev *dev = (void *) skb->sk;
349 atomic_sub(skb->truesize, &dev->wmem_alloc);
350 if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags))
David Herrmann96af7392011-10-24 15:30:58 +0200351 queue_work(system_nrt_wq, &dev->wakeup_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 rfcomm_dev_put(dev);
353}
354
355static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
356{
357 rfcomm_dev_hold(dev);
358 atomic_add(skb->truesize, &dev->wmem_alloc);
359 skb->sk = (void *) dev;
360 skb->destructor = rfcomm_wfree;
361}
362
Al Virodd0fc662005-10-07 07:46:04 +0100363static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364{
365 if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) {
366 struct sk_buff *skb = alloc_skb(size, priority);
367 if (skb) {
368 rfcomm_set_owner_w(skb, dev);
369 return skb;
370 }
371 }
372 return NULL;
373}
374
375/* ---- Device IOCTLs ---- */
376
377#define NOCAP_FLAGS ((1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP))
378
379static int rfcomm_create_dev(struct sock *sk, void __user *arg)
380{
381 struct rfcomm_dev_req req;
382 struct rfcomm_dlc *dlc;
383 int id;
384
385 if (copy_from_user(&req, arg, sizeof(req)))
386 return -EFAULT;
387
Ville Tervo8de0a152007-07-11 09:23:41 +0200388 BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
390 if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
391 return -EPERM;
392
393 if (req.flags & (1 << RFCOMM_REUSE_DLC)) {
394 /* Socket must be connected */
395 if (sk->sk_state != BT_CONNECTED)
396 return -EBADFD;
397
398 dlc = rfcomm_pi(sk)->dlc;
399 rfcomm_dlc_hold(dlc);
400 } else {
401 dlc = rfcomm_dlc_alloc(GFP_KERNEL);
402 if (!dlc)
403 return -ENOMEM;
404 }
405
406 id = rfcomm_dev_add(&req, dlc);
407 if (id < 0) {
408 rfcomm_dlc_put(dlc);
409 return id;
410 }
411
412 if (req.flags & (1 << RFCOMM_REUSE_DLC)) {
413 /* DLC is now used by device.
414 * Socket must be disconnected */
415 sk->sk_state = BT_CLOSED;
416 }
417
418 return id;
419}
420
421static int rfcomm_release_dev(void __user *arg)
422{
423 struct rfcomm_dev_req req;
424 struct rfcomm_dev *dev;
425
426 if (copy_from_user(&req, arg, sizeof(req)))
427 return -EFAULT;
428
Ville Tervo8de0a152007-07-11 09:23:41 +0200429 BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200431 dev = rfcomm_dev_get(req.dev_id);
432 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 return -ENODEV;
434
435 if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) {
436 rfcomm_dev_put(dev);
437 return -EPERM;
438 }
439
440 if (req.flags & (1 << RFCOMM_HANGUP_NOW))
441 rfcomm_dlc_close(dev->dlc, 0);
442
Mikko Rapeli84950cf2007-07-11 09:18:15 +0200443 /* Shut down TTY synchronously before freeing rfcomm_dev */
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200444 if (dev->port.tty)
445 tty_vhangup(dev->port.tty);
Mikko Rapeli84950cf2007-07-11 09:18:15 +0200446
Dave Young93d80742008-02-05 03:12:06 -0800447 if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
448 rfcomm_dev_del(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 rfcomm_dev_put(dev);
450 return 0;
451}
452
453static int rfcomm_get_dev_list(void __user *arg)
454{
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200455 struct rfcomm_dev *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 struct rfcomm_dev_list_req *dl;
457 struct rfcomm_dev_info *di;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 int n = 0, size, err;
459 u16 dev_num;
460
461 BT_DBG("");
462
463 if (get_user(dev_num, (u16 __user *) arg))
464 return -EFAULT;
465
466 if (!dev_num || dev_num > (PAGE_SIZE * 4) / sizeof(*di))
467 return -EINVAL;
468
469 size = sizeof(*dl) + dev_num * sizeof(*di);
470
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200471 dl = kmalloc(size, GFP_KERNEL);
472 if (!dl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 return -ENOMEM;
474
475 di = dl->dev_info;
476
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200477 spin_lock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200479 list_for_each_entry(dev, &rfcomm_dev_list, list) {
Ville Tervo8de0a152007-07-11 09:23:41 +0200480 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
481 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 (di + n)->id = dev->id;
483 (di + n)->flags = dev->flags;
484 (di + n)->state = dev->dlc->state;
485 (di + n)->channel = dev->channel;
486 bacpy(&(di + n)->src, &dev->src);
487 bacpy(&(di + n)->dst, &dev->dst);
488 if (++n >= dev_num)
489 break;
490 }
491
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200492 spin_unlock(&rfcomm_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
494 dl->dev_num = n;
495 size = sizeof(*dl) + n * sizeof(*di);
496
497 err = copy_to_user(arg, dl, size);
498 kfree(dl);
499
500 return err ? -EFAULT : 0;
501}
502
503static int rfcomm_get_dev_info(void __user *arg)
504{
505 struct rfcomm_dev *dev;
506 struct rfcomm_dev_info di;
507 int err = 0;
508
509 BT_DBG("");
510
511 if (copy_from_user(&di, arg, sizeof(di)))
512 return -EFAULT;
513
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200514 dev = rfcomm_dev_get(di.id);
515 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 return -ENODEV;
517
518 di.flags = dev->flags;
519 di.channel = dev->channel;
520 di.state = dev->dlc->state;
521 bacpy(&di.src, &dev->src);
522 bacpy(&di.dst, &dev->dst);
523
524 if (copy_to_user(arg, &di, sizeof(di)))
525 err = -EFAULT;
526
527 rfcomm_dev_put(dev);
528 return err;
529}
530
531int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
532{
533 BT_DBG("cmd %d arg %p", cmd, arg);
534
535 switch (cmd) {
536 case RFCOMMCREATEDEV:
537 return rfcomm_create_dev(sk, arg);
538
539 case RFCOMMRELEASEDEV:
540 return rfcomm_release_dev(arg);
541
542 case RFCOMMGETDEVLIST:
543 return rfcomm_get_dev_list(arg);
544
545 case RFCOMMGETDEVINFO:
546 return rfcomm_get_dev_info(arg);
547 }
548
549 return -EINVAL;
550}
551
552/* ---- DLC callbacks ---- */
553static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
554{
555 struct rfcomm_dev *dev = dlc->owner;
556 struct tty_struct *tty;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900557
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200558 if (!dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 kfree_skb(skb);
560 return;
561 }
562
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200563 tty = dev->port.tty;
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200564 if (!tty || !skb_queue_empty(&dev->pending)) {
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200565 skb_queue_tail(&dev->pending, skb);
566 return;
567 }
568
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);
570
Paul Fulghum817d6d32006-06-28 04:26:47 -0700571 tty_insert_flip_string(tty, skb->data, skb->len);
572 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
574 kfree_skb(skb);
575}
576
577static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
578{
579 struct rfcomm_dev *dev = dlc->owner;
580 if (!dev)
581 return;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900582
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
584
585 dev->err = err;
586 wake_up_interruptible(&dev->wait);
587
588 if (dlc->state == BT_CLOSED) {
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200589 if (!dev->port.tty) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
Dave Young537d59a2008-06-01 23:50:52 -0700591 /* Drop DLC lock here to avoid deadlock
592 * 1. rfcomm_dev_get will take rfcomm_dev_lock
593 * but in rfcomm_dev_add there's lock order:
594 * rfcomm_dev_lock -> dlc lock
595 * 2. rfcomm_dev_put will deadlock if it's
596 * the last reference
597 */
598 rfcomm_dlc_unlock(dlc);
599 if (rfcomm_dev_get(dev->id) == NULL) {
600 rfcomm_dlc_lock(dlc);
Marcel Holtmann77f2a452007-05-05 00:36:10 +0200601 return;
Dave Young537d59a2008-06-01 23:50:52 -0700602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Marcel Holtmann77f2a452007-05-05 00:36:10 +0200604 rfcomm_dev_del(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 rfcomm_dev_put(dev);
Dave Young537d59a2008-06-01 23:50:52 -0700606 rfcomm_dlc_lock(dlc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900608 } else
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200609 tty_hangup(dev->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 }
611}
612
613static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
614{
615 struct rfcomm_dev *dev = dlc->owner;
616 if (!dev)
617 return;
Timo Teräs7b9eb9e2005-08-09 20:28:21 -0700618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig);
620
Timo Teräs7b9eb9e2005-08-09 20:28:21 -0700621 if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) {
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200622 if (dev->port.tty && !C_CLOCAL(dev->port.tty))
623 tty_hangup(dev->port.tty);
Timo Teräs7b9eb9e2005-08-09 20:28:21 -0700624 }
625
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900626 dev->modem_status =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 ((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) |
628 ((v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0) |
629 ((v24_sig & RFCOMM_V24_IC) ? TIOCM_RI : 0) |
630 ((v24_sig & RFCOMM_V24_DV) ? TIOCM_CD : 0);
631}
632
633/* ---- TTY functions ---- */
David Herrmann96af7392011-10-24 15:30:58 +0200634static void rfcomm_tty_wakeup(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635{
David Herrmann96af7392011-10-24 15:30:58 +0200636 struct rfcomm_dev *dev = container_of(work, struct rfcomm_dev,
637 wakeup_task);
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200638 struct tty_struct *tty = dev->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 if (!tty)
640 return;
641
642 BT_DBG("dev %p tty %p", dev, tty);
Alan Coxa352def2008-07-16 21:53:12 +0100643 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644}
645
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200646static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
647{
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200648 struct tty_struct *tty = dev->port.tty;
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200649 struct sk_buff *skb;
650 int inserted = 0;
651
652 if (!tty)
653 return;
654
655 BT_DBG("dev %p tty %p", dev, tty);
656
657 rfcomm_dlc_lock(dev->dlc);
658
659 while ((skb = skb_dequeue(&dev->pending))) {
660 inserted += tty_insert_flip_string(tty, skb->data, skb->len);
661 kfree_skb(skb);
662 }
663
664 rfcomm_dlc_unlock(dev->dlc);
665
666 if (inserted > 0)
667 tty_flip_buffer_push(tty);
668}
669
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
671{
672 DECLARE_WAITQUEUE(wait, current);
673 struct rfcomm_dev *dev;
674 struct rfcomm_dlc *dlc;
675 int err, id;
676
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900677 id = tty->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
679 BT_DBG("tty %p id %d", tty, id);
680
681 /* We don't leak this refcount. For reasons which are not entirely
682 clear, the TTY layer will call our ->close() method even if the
683 open fails. We decrease the refcount there, and decreasing it
684 here too would cause breakage. */
685 dev = rfcomm_dev_get(id);
686 if (!dev)
687 return -ENODEV;
688
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100689 BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst),
690 dev->channel, atomic_read(&dev->opened));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100692 if (atomic_inc_return(&dev->opened) > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 return 0;
694
695 dlc = dev->dlc;
696
697 /* Attach TTY and open DLC */
698
699 rfcomm_dlc_lock(dlc);
700 tty->driver_data = dev;
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200701 dev->port.tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 rfcomm_dlc_unlock(dlc);
703 set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
704
705 err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);
706 if (err < 0)
707 return err;
708
709 /* Wait for DLC to connect */
710 add_wait_queue(&dev->wait, &wait);
711 while (1) {
712 set_current_state(TASK_INTERRUPTIBLE);
713
714 if (dlc->state == BT_CLOSED) {
715 err = -dev->err;
716 break;
717 }
718
719 if (dlc->state == BT_CONNECTED)
720 break;
721
722 if (signal_pending(current)) {
723 err = -EINTR;
724 break;
725 }
726
Vladislav P840af822011-02-14 15:21:50 -0200727 tty_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 schedule();
Vladislav P840af822011-02-14 15:21:50 -0200729 tty_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 }
731 set_current_state(TASK_RUNNING);
732 remove_wait_queue(&dev->wait, &wait);
733
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100734 if (err == 0)
Cornelia Huckffa6a702009-03-04 12:44:00 +0100735 device_move(dev->tty_dev, rfcomm_get_device(dev),
736 DPM_ORDER_DEV_AFTER_PARENT);
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100737
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200738 rfcomm_tty_copy_pending(dev);
739
740 rfcomm_dlc_unthrottle(dev->dlc);
741
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 return err;
743}
744
745static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
746{
747 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
748 if (!dev)
749 return;
750
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100751 BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
752 atomic_read(&dev->opened));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100754 if (atomic_dec_and_test(&dev->opened)) {
Dave Youngacea6852008-01-21 22:35:21 -0800755 if (dev->tty_dev->parent)
Cornelia Huckffa6a702009-03-04 12:44:00 +0100756 device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST);
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100757
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 /* Close DLC and dettach TTY */
759 rfcomm_dlc_close(dev->dlc, 0);
760
761 clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
David Herrmann96af7392011-10-24 15:30:58 +0200762 cancel_work_sync(&dev->wakeup_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
764 rfcomm_dlc_lock(dev->dlc);
765 tty->driver_data = NULL;
Jiri Slabyf60db8c2012-04-02 13:54:50 +0200766 dev->port.tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 rfcomm_dlc_unlock(dev->dlc);
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100768
769 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) {
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200770 spin_lock(&rfcomm_dev_lock);
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100771 list_del_init(&dev->list);
Gustavo F. Padovan393432c2011-12-27 15:28:45 -0200772 spin_unlock(&rfcomm_dev_lock);
Marcel Holtmann9a5df922008-11-30 12:17:29 +0100773
774 rfcomm_dev_put(dev);
775 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 }
777
778 rfcomm_dev_put(dev);
779}
780
781static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
782{
783 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
784 struct rfcomm_dlc *dlc = dev->dlc;
785 struct sk_buff *skb;
786 int err = 0, sent = 0, size;
787
788 BT_DBG("tty %p count %d", tty, count);
789
790 while (count) {
791 size = min_t(uint, count, dlc->mtu);
792
793 skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900794
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 if (!skb)
796 break;
797
798 skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
799
800 memcpy(skb_put(skb, size), buf + sent, size);
801
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200802 err = rfcomm_dlc_send(dlc, skb);
803 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 kfree_skb(skb);
805 break;
806 }
807
808 sent += size;
809 count -= size;
810 }
811
812 return sent ? sent : err;
813}
814
815static int rfcomm_tty_write_room(struct tty_struct *tty)
816{
817 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
818 int room;
819
820 BT_DBG("tty %p", tty);
821
Marcel Holtmannb6e557f2007-01-08 02:16:27 +0100822 if (!dev || !dev->dlc)
823 return 0;
824
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc);
826 if (room < 0)
827 room = 0;
Marcel Holtmannb6e557f2007-01-08 02:16:27 +0100828
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 return room;
830}
831
Alan Cox6caa76b2011-02-14 16:27:22 +0000832static int rfcomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833{
834 BT_DBG("tty %p cmd 0x%02x", tty, cmd);
835
836 switch (cmd) {
837 case TCGETS:
838 BT_DBG("TCGETS is not supported");
839 return -ENOIOCTLCMD;
840
841 case TCSETS:
842 BT_DBG("TCSETS is not supported");
843 return -ENOIOCTLCMD;
844
845 case TIOCMIWAIT:
846 BT_DBG("TIOCMIWAIT");
847 break;
848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 case TIOCGSERIAL:
850 BT_ERR("TIOCGSERIAL is not supported");
851 return -ENOIOCTLCMD;
852
853 case TIOCSSERIAL:
854 BT_ERR("TIOCSSERIAL is not supported");
855 return -ENOIOCTLCMD;
856
857 case TIOCSERGSTRUCT:
858 BT_ERR("TIOCSERGSTRUCT is not supported");
859 return -ENOIOCTLCMD;
860
861 case TIOCSERGETLSR:
862 BT_ERR("TIOCSERGETLSR is not supported");
863 return -ENOIOCTLCMD;
864
865 case TIOCSERCONFIG:
866 BT_ERR("TIOCSERCONFIG is not supported");
867 return -ENOIOCTLCMD;
868
869 default:
870 return -ENOIOCTLCMD; /* ioctls which we must ignore */
871
872 }
873
874 return -ENOIOCTLCMD;
875}
876
Alan Cox606d0992006-12-08 02:38:45 -0800877static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878{
Alan Cox606d0992006-12-08 02:38:45 -0800879 struct ktermios *new = tty->termios;
J. Suter3a5e9032005-08-09 20:28:46 -0700880 int old_baud_rate = tty_termios_baud_rate(old);
881 int new_baud_rate = tty_termios_baud_rate(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
J. Suter3a5e9032005-08-09 20:28:46 -0700883 u8 baud, data_bits, stop_bits, parity, x_on, x_off;
884 u16 changes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
J. Suter3a5e9032005-08-09 20:28:46 -0700886 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
887
888 BT_DBG("tty %p termios %p", tty, old);
889
Marcel Holtmannff2d3672006-11-18 22:14:42 +0100890 if (!dev || !dev->dlc || !dev->dlc->session)
Marcel Holtmanncb19d9e2006-10-15 17:31:10 +0200891 return;
892
J. Suter3a5e9032005-08-09 20:28:46 -0700893 /* Handle turning off CRTSCTS */
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900894 if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS))
J. Suter3a5e9032005-08-09 20:28:46 -0700895 BT_DBG("Turning off CRTSCTS unsupported");
896
897 /* Parity on/off and when on, odd/even */
898 if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) ||
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200899 ((old->c_cflag & PARODD) != (new->c_cflag & PARODD))) {
J. Suter3a5e9032005-08-09 20:28:46 -0700900 changes |= RFCOMM_RPN_PM_PARITY;
901 BT_DBG("Parity change detected.");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 }
J. Suter3a5e9032005-08-09 20:28:46 -0700903
904 /* Mark and space parity are not supported! */
905 if (new->c_cflag & PARENB) {
906 if (new->c_cflag & PARODD) {
907 BT_DBG("Parity is ODD");
908 parity = RFCOMM_RPN_PARITY_ODD;
909 } else {
910 BT_DBG("Parity is EVEN");
911 parity = RFCOMM_RPN_PARITY_EVEN;
912 }
913 } else {
914 BT_DBG("Parity is OFF");
915 parity = RFCOMM_RPN_PARITY_NONE;
916 }
917
918 /* Setting the x_on / x_off characters */
919 if (old->c_cc[VSTOP] != new->c_cc[VSTOP]) {
920 BT_DBG("XOFF custom");
921 x_on = new->c_cc[VSTOP];
922 changes |= RFCOMM_RPN_PM_XON;
923 } else {
924 BT_DBG("XOFF default");
925 x_on = RFCOMM_RPN_XON_CHAR;
926 }
927
928 if (old->c_cc[VSTART] != new->c_cc[VSTART]) {
929 BT_DBG("XON custom");
930 x_off = new->c_cc[VSTART];
931 changes |= RFCOMM_RPN_PM_XOFF;
932 } else {
933 BT_DBG("XON default");
934 x_off = RFCOMM_RPN_XOFF_CHAR;
935 }
936
937 /* Handle setting of stop bits */
938 if ((old->c_cflag & CSTOPB) != (new->c_cflag & CSTOPB))
939 changes |= RFCOMM_RPN_PM_STOP;
940
941 /* POSIX does not support 1.5 stop bits and RFCOMM does not
942 * support 2 stop bits. So a request for 2 stop bits gets
943 * translated to 1.5 stop bits */
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200944 if (new->c_cflag & CSTOPB)
J. Suter3a5e9032005-08-09 20:28:46 -0700945 stop_bits = RFCOMM_RPN_STOP_15;
Andrei Emeltchenko285b4e92010-12-01 16:58:23 +0200946 else
J. Suter3a5e9032005-08-09 20:28:46 -0700947 stop_bits = RFCOMM_RPN_STOP_1;
J. Suter3a5e9032005-08-09 20:28:46 -0700948
949 /* Handle number of data bits [5-8] */
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900950 if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE))
J. Suter3a5e9032005-08-09 20:28:46 -0700951 changes |= RFCOMM_RPN_PM_DATA;
952
953 switch (new->c_cflag & CSIZE) {
954 case CS5:
955 data_bits = RFCOMM_RPN_DATA_5;
956 break;
957 case CS6:
958 data_bits = RFCOMM_RPN_DATA_6;
959 break;
960 case CS7:
961 data_bits = RFCOMM_RPN_DATA_7;
962 break;
963 case CS8:
964 data_bits = RFCOMM_RPN_DATA_8;
965 break;
966 default:
967 data_bits = RFCOMM_RPN_DATA_8;
968 break;
969 }
970
971 /* Handle baudrate settings */
972 if (old_baud_rate != new_baud_rate)
973 changes |= RFCOMM_RPN_PM_BITRATE;
974
975 switch (new_baud_rate) {
976 case 2400:
977 baud = RFCOMM_RPN_BR_2400;
978 break;
979 case 4800:
980 baud = RFCOMM_RPN_BR_4800;
981 break;
982 case 7200:
983 baud = RFCOMM_RPN_BR_7200;
984 break;
985 case 9600:
986 baud = RFCOMM_RPN_BR_9600;
987 break;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900988 case 19200:
J. Suter3a5e9032005-08-09 20:28:46 -0700989 baud = RFCOMM_RPN_BR_19200;
990 break;
991 case 38400:
992 baud = RFCOMM_RPN_BR_38400;
993 break;
994 case 57600:
995 baud = RFCOMM_RPN_BR_57600;
996 break;
997 case 115200:
998 baud = RFCOMM_RPN_BR_115200;
999 break;
1000 case 230400:
1001 baud = RFCOMM_RPN_BR_230400;
1002 break;
1003 default:
1004 /* 9600 is standard accordinag to the RFCOMM specification */
1005 baud = RFCOMM_RPN_BR_9600;
1006 break;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001007
J. Suter3a5e9032005-08-09 20:28:46 -07001008 }
1009
1010 if (changes)
1011 rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud,
1012 data_bits, stop_bits, parity,
1013 RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014}
1015
1016static void rfcomm_tty_throttle(struct tty_struct *tty)
1017{
1018 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1019
1020 BT_DBG("tty %p dev %p", tty, dev);
J. Suter3a5e9032005-08-09 20:28:46 -07001021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 rfcomm_dlc_throttle(dev->dlc);
1023}
1024
1025static void rfcomm_tty_unthrottle(struct tty_struct *tty)
1026{
1027 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1028
1029 BT_DBG("tty %p dev %p", tty, dev);
J. Suter3a5e9032005-08-09 20:28:46 -07001030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 rfcomm_dlc_unthrottle(dev->dlc);
1032}
1033
1034static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty)
1035{
1036 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
1038 BT_DBG("tty %p dev %p", tty, dev);
1039
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001040 if (!dev || !dev->dlc)
1041 return 0;
1042
1043 if (!skb_queue_empty(&dev->dlc->tx_queue))
1044 return dev->dlc->mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
1046 return 0;
1047}
1048
1049static void rfcomm_tty_flush_buffer(struct tty_struct *tty)
1050{
1051 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 BT_DBG("tty %p dev %p", tty, dev);
1054
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001055 if (!dev || !dev->dlc)
1056 return;
1057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 skb_queue_purge(&dev->dlc->tx_queue);
Alan Coxa352def2008-07-16 21:53:12 +01001059 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060}
1061
1062static void rfcomm_tty_send_xchar(struct tty_struct *tty, char ch)
1063{
1064 BT_DBG("tty %p ch %c", tty, ch);
1065}
1066
1067static void rfcomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
1068{
1069 BT_DBG("tty %p timeout %d", tty, timeout);
1070}
1071
1072static void rfcomm_tty_hangup(struct tty_struct *tty)
1073{
1074 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
1076 BT_DBG("tty %p dev %p", tty, dev);
1077
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001078 if (!dev)
1079 return;
1080
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 rfcomm_tty_flush_buffer(tty);
1082
Marcel Holtmann77f2a452007-05-05 00:36:10 +02001083 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
1084 if (rfcomm_dev_get(dev->id) == NULL)
1085 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 rfcomm_dev_del(dev);
Marcel Holtmann77f2a452007-05-05 00:36:10 +02001087 rfcomm_dev_put(dev);
1088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089}
1090
Alan Cox60b33c12011-02-14 16:26:14 +00001091static int rfcomm_tty_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092{
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001093 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095 BT_DBG("tty %p dev %p", tty, dev);
1096
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001097 return dev->modem_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098}
1099
Alan Cox20b9d172011-02-14 16:26:50 +00001100static int rfcomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101{
J. Suter3a5e9032005-08-09 20:28:46 -07001102 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1103 struct rfcomm_dlc *dlc = dev->dlc;
1104 u8 v24_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
1106 BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear);
1107
J. Suter3a5e9032005-08-09 20:28:46 -07001108 rfcomm_dlc_get_modem_status(dlc, &v24_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
J. Suter3a5e9032005-08-09 20:28:46 -07001110 if (set & TIOCM_DSR || set & TIOCM_DTR)
1111 v24_sig |= RFCOMM_V24_RTC;
1112 if (set & TIOCM_RTS || set & TIOCM_CTS)
1113 v24_sig |= RFCOMM_V24_RTR;
1114 if (set & TIOCM_RI)
1115 v24_sig |= RFCOMM_V24_IC;
1116 if (set & TIOCM_CD)
1117 v24_sig |= RFCOMM_V24_DV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
J. Suter3a5e9032005-08-09 20:28:46 -07001119 if (clear & TIOCM_DSR || clear & TIOCM_DTR)
1120 v24_sig &= ~RFCOMM_V24_RTC;
1121 if (clear & TIOCM_RTS || clear & TIOCM_CTS)
1122 v24_sig &= ~RFCOMM_V24_RTR;
1123 if (clear & TIOCM_RI)
1124 v24_sig &= ~RFCOMM_V24_IC;
1125 if (clear & TIOCM_CD)
1126 v24_sig &= ~RFCOMM_V24_DV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
J. Suter3a5e9032005-08-09 20:28:46 -07001128 rfcomm_dlc_set_modem_status(dlc, v24_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
J. Suter3a5e9032005-08-09 20:28:46 -07001130 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131}
1132
1133/* ---- TTY structure ---- */
1134
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001135static const struct tty_operations rfcomm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 .open = rfcomm_tty_open,
1137 .close = rfcomm_tty_close,
1138 .write = rfcomm_tty_write,
1139 .write_room = rfcomm_tty_write_room,
1140 .chars_in_buffer = rfcomm_tty_chars_in_buffer,
1141 .flush_buffer = rfcomm_tty_flush_buffer,
1142 .ioctl = rfcomm_tty_ioctl,
1143 .throttle = rfcomm_tty_throttle,
1144 .unthrottle = rfcomm_tty_unthrottle,
1145 .set_termios = rfcomm_tty_set_termios,
1146 .send_xchar = rfcomm_tty_send_xchar,
1147 .hangup = rfcomm_tty_hangup,
1148 .wait_until_sent = rfcomm_tty_wait_until_sent,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 .tiocmget = rfcomm_tty_tiocmget,
1150 .tiocmset = rfcomm_tty_tiocmset,
1151};
1152
Gustavo F. Padovan2f8362a2010-07-24 02:04:45 -03001153int __init rfcomm_init_ttys(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
David Herrmann5ada9912011-10-24 15:30:57 +02001155 int error;
1156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
1158 if (!rfcomm_tty_driver)
David Herrmann5ada9912011-10-24 15:30:57 +02001159 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 rfcomm_tty_driver->driver_name = "rfcomm";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 rfcomm_tty_driver->name = "rfcomm";
1163 rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR;
1164 rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR;
1165 rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1166 rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001167 rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 rfcomm_tty_driver->init_termios = tty_std_termios;
1169 rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Marcel Holtmannca37bdd2008-07-14 20:13:52 +02001170 rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
1172
David Herrmann5ada9912011-10-24 15:30:57 +02001173 error = tty_register_driver(rfcomm_tty_driver);
1174 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 BT_ERR("Can't register RFCOMM TTY driver");
1176 put_tty_driver(rfcomm_tty_driver);
David Herrmann5ada9912011-10-24 15:30:57 +02001177 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 }
1179
1180 BT_INFO("RFCOMM TTY layer initialized");
1181
1182 return 0;
1183}
1184
Gustavo F. Padovan28e95092010-07-31 19:57:05 -03001185void rfcomm_cleanup_ttys(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186{
1187 tty_unregister_driver(rfcomm_tty_driver);
1188 put_tty_driver(rfcomm_tty_driver);
1189}