blob: ec22ebe0c2c8ba097d4f6ee2ca6a0b754ccbd7c6 [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.
26 *
27 * $Id: tty.c,v 1.24 2002/10/03 01:54:38 holtmann Exp $
28 */
29
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/module.h>
31
32#include <linux/tty.h>
33#include <linux/tty_driver.h>
34#include <linux/tty_flip.h>
35
Randy Dunlap4fc268d2006-01-11 12:17:47 -080036#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/slab.h>
38#include <linux/skbuff.h>
39
40#include <net/bluetooth/bluetooth.h>
Marcel Holtmann0a85b962006-07-06 13:09:02 +020041#include <net/bluetooth/hci_core.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <net/bluetooth/rfcomm.h>
43
44#ifndef CONFIG_BT_RFCOMM_DEBUG
45#undef BT_DBG
46#define BT_DBG(D...)
47#endif
48
49#define RFCOMM_TTY_MAGIC 0x6d02 /* magic number for rfcomm struct */
50#define RFCOMM_TTY_PORTS RFCOMM_MAX_DEV /* whole lotta rfcomm devices */
51#define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */
52#define RFCOMM_TTY_MINOR 0
53
54static struct tty_driver *rfcomm_tty_driver;
55
56struct rfcomm_dev {
57 struct list_head list;
58 atomic_t refcnt;
59
60 char name[12];
61 int id;
62 unsigned long flags;
63 int opened;
64 int err;
65
66 bdaddr_t src;
67 bdaddr_t dst;
68 u8 channel;
69
70 uint modem_status;
71
72 struct rfcomm_dlc *dlc;
73 struct tty_struct *tty;
74 wait_queue_head_t wait;
75 struct tasklet_struct wakeup_task;
76
Marcel Holtmannc1a33132007-02-17 23:58:57 +010077 struct device *tty_dev;
78
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 atomic_t wmem_alloc;
Marcel Holtmanna0c22f22008-07-14 20:13:52 +020080
81 struct sk_buff_head pending;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082};
83
84static LIST_HEAD(rfcomm_dev_list);
85static DEFINE_RWLOCK(rfcomm_dev_lock);
86
87static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb);
88static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err);
89static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig);
90
91static void rfcomm_tty_wakeup(unsigned long arg);
92
93/* ---- Device functions ---- */
94static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
95{
96 struct rfcomm_dlc *dlc = dev->dlc;
97
98 BT_DBG("dev %p dlc %p", dev, dlc);
99
Dave Youngf9513752008-01-10 22:22:52 -0800100 /* Refcount should only hit zero when called from rfcomm_dev_del()
101 which will have taken us off the list. Everything else are
102 refcounting bugs. */
103 BUG_ON(!list_empty(&dev->list));
Ville Tervo8de0a152007-07-11 09:23:41 +0200104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 rfcomm_dlc_lock(dlc);
106 /* Detach DLC if it's owned by this dev */
107 if (dlc->owner == dev)
108 dlc->owner = NULL;
109 rfcomm_dlc_unlock(dlc);
110
111 rfcomm_dlc_put(dlc);
112
113 tty_unregister_device(rfcomm_tty_driver, dev->id);
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 kfree(dev);
116
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900117 /* It's safe to call module_put() here because socket still
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 holds reference to this module. */
119 module_put(THIS_MODULE);
120}
121
122static inline void rfcomm_dev_hold(struct rfcomm_dev *dev)
123{
124 atomic_inc(&dev->refcnt);
125}
126
127static inline void rfcomm_dev_put(struct rfcomm_dev *dev)
128{
129 /* The reason this isn't actually a race, as you no
130 doubt have a little voice screaming at you in your
131 head, is that the refcount should never actually
132 reach zero unless the device has already been taken
133 off the list, in rfcomm_dev_del(). And if that's not
134 true, we'll hit the BUG() in rfcomm_dev_destruct()
135 anyway. */
136 if (atomic_dec_and_test(&dev->refcnt))
137 rfcomm_dev_destruct(dev);
138}
139
140static struct rfcomm_dev *__rfcomm_dev_get(int id)
141{
142 struct rfcomm_dev *dev;
143 struct list_head *p;
144
145 list_for_each(p, &rfcomm_dev_list) {
146 dev = list_entry(p, struct rfcomm_dev, list);
147 if (dev->id == id)
148 return dev;
149 }
150
151 return NULL;
152}
153
154static inline struct rfcomm_dev *rfcomm_dev_get(int id)
155{
156 struct rfcomm_dev *dev;
157
158 read_lock(&rfcomm_dev_lock);
159
160 dev = __rfcomm_dev_get(id);
Ville Tervo8de0a152007-07-11 09:23:41 +0200161
162 if (dev) {
163 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
164 dev = NULL;
165 else
166 rfcomm_dev_hold(dev);
167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
169 read_unlock(&rfcomm_dev_lock);
170
171 return dev;
172}
173
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200174static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
175{
176 struct hci_dev *hdev;
177 struct hci_conn *conn;
178
179 hdev = hci_get_route(&dev->dst, &dev->src);
180 if (!hdev)
181 return NULL;
182
183 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200184
185 hci_dev_put(hdev);
186
Marcel Holtmannb2cfcd72006-10-15 17:31:05 +0200187 return conn ? &conn->dev : NULL;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200188}
189
Marcel Holtmanndae6a0f2007-10-20 14:52:38 +0200190static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
191{
192 struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
193 bdaddr_t bdaddr;
194 baswap(&bdaddr, &dev->dst);
195 return sprintf(buf, "%s\n", batostr(&bdaddr));
196}
197
198static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf)
199{
200 struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
201 return sprintf(buf, "%d\n", dev->channel);
202}
203
204static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
205static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL);
206
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
208{
209 struct rfcomm_dev *dev;
210 struct list_head *head = &rfcomm_dev_list, *p;
211 int err = 0;
212
213 BT_DBG("id %d channel %d", req->dev_id, req->channel);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900214
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200215 dev = kzalloc(sizeof(struct rfcomm_dev), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 if (!dev)
217 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
219 write_lock_bh(&rfcomm_dev_lock);
220
221 if (req->dev_id < 0) {
222 dev->id = 0;
223
224 list_for_each(p, &rfcomm_dev_list) {
225 if (list_entry(p, struct rfcomm_dev, list)->id != dev->id)
226 break;
227
228 dev->id++;
229 head = p;
230 }
231 } else {
232 dev->id = req->dev_id;
233
234 list_for_each(p, &rfcomm_dev_list) {
235 struct rfcomm_dev *entry = list_entry(p, struct rfcomm_dev, list);
236
237 if (entry->id == dev->id) {
238 err = -EADDRINUSE;
239 goto out;
240 }
241
242 if (entry->id > dev->id - 1)
243 break;
244
245 head = p;
246 }
247 }
248
249 if ((dev->id < 0) || (dev->id > RFCOMM_MAX_DEV - 1)) {
250 err = -ENFILE;
251 goto out;
252 }
253
254 sprintf(dev->name, "rfcomm%d", dev->id);
255
256 list_add(&dev->list, head);
257 atomic_set(&dev->refcnt, 1);
258
259 bacpy(&dev->src, &req->src);
260 bacpy(&dev->dst, &req->dst);
261 dev->channel = req->channel;
262
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900263 dev->flags = req->flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 ((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
265
266 init_waitqueue_head(&dev->wait);
267 tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
268
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200269 skb_queue_head_init(&dev->pending);
270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 rfcomm_dlc_lock(dlc);
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200272
273 if (req->flags & (1 << RFCOMM_REUSE_DLC)) {
274 struct sock *sk = dlc->owner;
275 struct sk_buff *skb;
276
277 BUG_ON(!sk);
278
279 rfcomm_dlc_throttle(dlc);
280
281 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
282 skb_orphan(skb);
283 skb_queue_tail(&dev->pending, skb);
284 atomic_sub(skb->len, &sk->sk_rmem_alloc);
285 }
286 }
287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 dlc->data_ready = rfcomm_dev_data_ready;
289 dlc->state_change = rfcomm_dev_state_change;
290 dlc->modem_status = rfcomm_dev_modem_status;
291
292 dlc->owner = dev;
293 dev->dlc = dlc;
Marcel Holtmann8b6b3da2008-07-14 20:13:52 +0200294
295 rfcomm_dev_modem_status(dlc, dlc->remote_v24_sig);
296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 rfcomm_dlc_unlock(dlc);
298
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900299 /* It's safe to call __module_get() here because socket already
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 holds reference to this module. */
301 __module_get(THIS_MODULE);
302
303out:
304 write_unlock_bh(&rfcomm_dev_lock);
305
Marcel Holtmann09c7d822007-07-26 00:12:25 -0700306 if (err < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 kfree(dev);
308 return err;
309 }
310
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100311 dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Ville Tervo8de0a152007-07-11 09:23:41 +0200313 if (IS_ERR(dev->tty_dev)) {
Marcel Holtmann09c7d822007-07-26 00:12:25 -0700314 err = PTR_ERR(dev->tty_dev);
Ville Tervo8de0a152007-07-11 09:23:41 +0200315 list_del(&dev->list);
316 kfree(dev);
Marcel Holtmann09c7d822007-07-26 00:12:25 -0700317 return err;
Ville Tervo8de0a152007-07-11 09:23:41 +0200318 }
319
Marcel Holtmanndae6a0f2007-10-20 14:52:38 +0200320 dev_set_drvdata(dev->tty_dev, dev);
321
322 if (device_create_file(dev->tty_dev, &dev_attr_address) < 0)
323 BT_ERR("Failed to create address attribute");
324
325 if (device_create_file(dev->tty_dev, &dev_attr_channel) < 0)
326 BT_ERR("Failed to create channel attribute");
327
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 return dev->id;
329}
330
331static void rfcomm_dev_del(struct rfcomm_dev *dev)
332{
333 BT_DBG("dev %p", dev);
334
Dave Youngf9513752008-01-10 22:22:52 -0800335 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
336 BUG_ON(1);
337 else
338 set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
339
340 write_lock_bh(&rfcomm_dev_lock);
341 list_del_init(&dev->list);
342 write_unlock_bh(&rfcomm_dev_lock);
343
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 rfcomm_dev_put(dev);
345}
346
347/* ---- Send buffer ---- */
348static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
349{
350 /* We can't let it be zero, because we don't get a callback
351 when tx_credits becomes nonzero, hence we'd never wake up */
352 return dlc->mtu * (dlc->tx_credits?:1);
353}
354
355static void rfcomm_wfree(struct sk_buff *skb)
356{
357 struct rfcomm_dev *dev = (void *) skb->sk;
358 atomic_sub(skb->truesize, &dev->wmem_alloc);
359 if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags))
360 tasklet_schedule(&dev->wakeup_task);
361 rfcomm_dev_put(dev);
362}
363
364static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev)
365{
366 rfcomm_dev_hold(dev);
367 atomic_add(skb->truesize, &dev->wmem_alloc);
368 skb->sk = (void *) dev;
369 skb->destructor = rfcomm_wfree;
370}
371
Al Virodd0fc662005-10-07 07:46:04 +0100372static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) {
375 struct sk_buff *skb = alloc_skb(size, priority);
376 if (skb) {
377 rfcomm_set_owner_w(skb, dev);
378 return skb;
379 }
380 }
381 return NULL;
382}
383
384/* ---- Device IOCTLs ---- */
385
386#define NOCAP_FLAGS ((1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP))
387
388static int rfcomm_create_dev(struct sock *sk, void __user *arg)
389{
390 struct rfcomm_dev_req req;
391 struct rfcomm_dlc *dlc;
392 int id;
393
394 if (copy_from_user(&req, arg, sizeof(req)))
395 return -EFAULT;
396
Ville Tervo8de0a152007-07-11 09:23:41 +0200397 BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
399 if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
400 return -EPERM;
401
402 if (req.flags & (1 << RFCOMM_REUSE_DLC)) {
403 /* Socket must be connected */
404 if (sk->sk_state != BT_CONNECTED)
405 return -EBADFD;
406
407 dlc = rfcomm_pi(sk)->dlc;
408 rfcomm_dlc_hold(dlc);
409 } else {
410 dlc = rfcomm_dlc_alloc(GFP_KERNEL);
411 if (!dlc)
412 return -ENOMEM;
413 }
414
415 id = rfcomm_dev_add(&req, dlc);
416 if (id < 0) {
417 rfcomm_dlc_put(dlc);
418 return id;
419 }
420
421 if (req.flags & (1 << RFCOMM_REUSE_DLC)) {
422 /* DLC is now used by device.
423 * Socket must be disconnected */
424 sk->sk_state = BT_CLOSED;
425 }
426
427 return id;
428}
429
430static int rfcomm_release_dev(void __user *arg)
431{
432 struct rfcomm_dev_req req;
433 struct rfcomm_dev *dev;
434
435 if (copy_from_user(&req, arg, sizeof(req)))
436 return -EFAULT;
437
Ville Tervo8de0a152007-07-11 09:23:41 +0200438 BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
440 if (!(dev = rfcomm_dev_get(req.dev_id)))
441 return -ENODEV;
442
443 if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) {
444 rfcomm_dev_put(dev);
445 return -EPERM;
446 }
447
448 if (req.flags & (1 << RFCOMM_HANGUP_NOW))
449 rfcomm_dlc_close(dev->dlc, 0);
450
Mikko Rapeli84950cf2007-07-11 09:18:15 +0200451 /* Shut down TTY synchronously before freeing rfcomm_dev */
452 if (dev->tty)
453 tty_vhangup(dev->tty);
454
Dave Young93d80742008-02-05 03:12:06 -0800455 if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
456 rfcomm_dev_del(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 rfcomm_dev_put(dev);
458 return 0;
459}
460
461static int rfcomm_get_dev_list(void __user *arg)
462{
463 struct rfcomm_dev_list_req *dl;
464 struct rfcomm_dev_info *di;
465 struct list_head *p;
466 int n = 0, size, err;
467 u16 dev_num;
468
469 BT_DBG("");
470
471 if (get_user(dev_num, (u16 __user *) arg))
472 return -EFAULT;
473
474 if (!dev_num || dev_num > (PAGE_SIZE * 4) / sizeof(*di))
475 return -EINVAL;
476
477 size = sizeof(*dl) + dev_num * sizeof(*di);
478
479 if (!(dl = kmalloc(size, GFP_KERNEL)))
480 return -ENOMEM;
481
482 di = dl->dev_info;
483
484 read_lock_bh(&rfcomm_dev_lock);
485
486 list_for_each(p, &rfcomm_dev_list) {
487 struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list);
Ville Tervo8de0a152007-07-11 09:23:41 +0200488 if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
489 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 (di + n)->id = dev->id;
491 (di + n)->flags = dev->flags;
492 (di + n)->state = dev->dlc->state;
493 (di + n)->channel = dev->channel;
494 bacpy(&(di + n)->src, &dev->src);
495 bacpy(&(di + n)->dst, &dev->dst);
496 if (++n >= dev_num)
497 break;
498 }
499
500 read_unlock_bh(&rfcomm_dev_lock);
501
502 dl->dev_num = n;
503 size = sizeof(*dl) + n * sizeof(*di);
504
505 err = copy_to_user(arg, dl, size);
506 kfree(dl);
507
508 return err ? -EFAULT : 0;
509}
510
511static int rfcomm_get_dev_info(void __user *arg)
512{
513 struct rfcomm_dev *dev;
514 struct rfcomm_dev_info di;
515 int err = 0;
516
517 BT_DBG("");
518
519 if (copy_from_user(&di, arg, sizeof(di)))
520 return -EFAULT;
521
522 if (!(dev = rfcomm_dev_get(di.id)))
523 return -ENODEV;
524
525 di.flags = dev->flags;
526 di.channel = dev->channel;
527 di.state = dev->dlc->state;
528 bacpy(&di.src, &dev->src);
529 bacpy(&di.dst, &dev->dst);
530
531 if (copy_to_user(arg, &di, sizeof(di)))
532 err = -EFAULT;
533
534 rfcomm_dev_put(dev);
535 return err;
536}
537
538int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
539{
540 BT_DBG("cmd %d arg %p", cmd, arg);
541
542 switch (cmd) {
543 case RFCOMMCREATEDEV:
544 return rfcomm_create_dev(sk, arg);
545
546 case RFCOMMRELEASEDEV:
547 return rfcomm_release_dev(arg);
548
549 case RFCOMMGETDEVLIST:
550 return rfcomm_get_dev_list(arg);
551
552 case RFCOMMGETDEVINFO:
553 return rfcomm_get_dev_info(arg);
554 }
555
556 return -EINVAL;
557}
558
559/* ---- DLC callbacks ---- */
560static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
561{
562 struct rfcomm_dev *dev = dlc->owner;
563 struct tty_struct *tty;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900564
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200565 if (!dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 kfree_skb(skb);
567 return;
568 }
569
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200570 if (!(tty = dev->tty) || !skb_queue_empty(&dev->pending)) {
571 skb_queue_tail(&dev->pending, skb);
572 return;
573 }
574
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);
576
Paul Fulghum817d6d32006-06-28 04:26:47 -0700577 tty_insert_flip_string(tty, skb->data, skb->len);
578 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
580 kfree_skb(skb);
581}
582
583static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
584{
585 struct rfcomm_dev *dev = dlc->owner;
586 if (!dev)
587 return;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900588
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
590
591 dev->err = err;
592 wake_up_interruptible(&dev->wait);
593
594 if (dlc->state == BT_CLOSED) {
595 if (!dev->tty) {
596 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
Dave Young537d59a2008-06-01 23:50:52 -0700597 /* Drop DLC lock here to avoid deadlock
598 * 1. rfcomm_dev_get will take rfcomm_dev_lock
599 * but in rfcomm_dev_add there's lock order:
600 * rfcomm_dev_lock -> dlc lock
601 * 2. rfcomm_dev_put will deadlock if it's
602 * the last reference
603 */
604 rfcomm_dlc_unlock(dlc);
605 if (rfcomm_dev_get(dev->id) == NULL) {
606 rfcomm_dlc_lock(dlc);
Marcel Holtmann77f2a452007-05-05 00:36:10 +0200607 return;
Dave Young537d59a2008-06-01 23:50:52 -0700608 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Marcel Holtmann77f2a452007-05-05 00:36:10 +0200610 rfcomm_dev_del(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 rfcomm_dev_put(dev);
Dave Young537d59a2008-06-01 23:50:52 -0700612 rfcomm_dlc_lock(dlc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 }
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900614 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 tty_hangup(dev->tty);
616 }
617}
618
619static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
620{
621 struct rfcomm_dev *dev = dlc->owner;
622 if (!dev)
623 return;
Timo Teräs7b9eb9e2005-08-09 20:28:21 -0700624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig);
626
Timo Teräs7b9eb9e2005-08-09 20:28:21 -0700627 if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) {
628 if (dev->tty && !C_CLOCAL(dev->tty))
629 tty_hangup(dev->tty);
630 }
631
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900632 dev->modem_status =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 ((v24_sig & RFCOMM_V24_RTC) ? (TIOCM_DSR | TIOCM_DTR) : 0) |
634 ((v24_sig & RFCOMM_V24_RTR) ? (TIOCM_RTS | TIOCM_CTS) : 0) |
635 ((v24_sig & RFCOMM_V24_IC) ? TIOCM_RI : 0) |
636 ((v24_sig & RFCOMM_V24_DV) ? TIOCM_CD : 0);
637}
638
639/* ---- TTY functions ---- */
640static void rfcomm_tty_wakeup(unsigned long arg)
641{
642 struct rfcomm_dev *dev = (void *) arg;
643 struct tty_struct *tty = dev->tty;
644 if (!tty)
645 return;
646
647 BT_DBG("dev %p tty %p", dev, tty);
648
649 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900650 (tty->ldisc.write_wakeup)(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
652 wake_up_interruptible(&tty->write_wait);
653#ifdef SERIAL_HAVE_POLL_WAIT
654 wake_up_interruptible(&tty->poll_wait);
655#endif
656}
657
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200658static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
659{
660 struct tty_struct *tty = dev->tty;
661 struct sk_buff *skb;
662 int inserted = 0;
663
664 if (!tty)
665 return;
666
667 BT_DBG("dev %p tty %p", dev, tty);
668
669 rfcomm_dlc_lock(dev->dlc);
670
671 while ((skb = skb_dequeue(&dev->pending))) {
672 inserted += tty_insert_flip_string(tty, skb->data, skb->len);
673 kfree_skb(skb);
674 }
675
676 rfcomm_dlc_unlock(dev->dlc);
677
678 if (inserted > 0)
679 tty_flip_buffer_push(tty);
680}
681
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
683{
684 DECLARE_WAITQUEUE(wait, current);
685 struct rfcomm_dev *dev;
686 struct rfcomm_dlc *dlc;
687 int err, id;
688
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900689 id = tty->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
691 BT_DBG("tty %p id %d", tty, id);
692
693 /* We don't leak this refcount. For reasons which are not entirely
694 clear, the TTY layer will call our ->close() method even if the
695 open fails. We decrease the refcount there, and decreasing it
696 here too would cause breakage. */
697 dev = rfcomm_dev_get(id);
698 if (!dev)
699 return -ENODEV;
700
701 BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), dev->channel, dev->opened);
702
703 if (dev->opened++ != 0)
704 return 0;
705
706 dlc = dev->dlc;
707
708 /* Attach TTY and open DLC */
709
710 rfcomm_dlc_lock(dlc);
711 tty->driver_data = dev;
712 dev->tty = tty;
713 rfcomm_dlc_unlock(dlc);
714 set_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
715
716 err = rfcomm_dlc_open(dlc, &dev->src, &dev->dst, dev->channel);
717 if (err < 0)
718 return err;
719
720 /* Wait for DLC to connect */
721 add_wait_queue(&dev->wait, &wait);
722 while (1) {
723 set_current_state(TASK_INTERRUPTIBLE);
724
725 if (dlc->state == BT_CLOSED) {
726 err = -dev->err;
727 break;
728 }
729
730 if (dlc->state == BT_CONNECTED)
731 break;
732
733 if (signal_pending(current)) {
734 err = -EINTR;
735 break;
736 }
737
738 schedule();
739 }
740 set_current_state(TASK_RUNNING);
741 remove_wait_queue(&dev->wait, &wait);
742
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100743 if (err == 0)
744 device_move(dev->tty_dev, rfcomm_get_device(dev));
745
Marcel Holtmanna0c22f22008-07-14 20:13:52 +0200746 rfcomm_tty_copy_pending(dev);
747
748 rfcomm_dlc_unthrottle(dev->dlc);
749
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 return err;
751}
752
753static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
754{
755 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
756 if (!dev)
757 return;
758
759 BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);
760
761 if (--dev->opened == 0) {
Dave Youngacea6852008-01-21 22:35:21 -0800762 if (dev->tty_dev->parent)
763 device_move(dev->tty_dev, NULL);
Marcel Holtmannc1a33132007-02-17 23:58:57 +0100764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 /* Close DLC and dettach TTY */
766 rfcomm_dlc_close(dev->dlc, 0);
767
768 clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags);
769 tasklet_kill(&dev->wakeup_task);
770
771 rfcomm_dlc_lock(dev->dlc);
772 tty->driver_data = NULL;
773 dev->tty = NULL;
774 rfcomm_dlc_unlock(dev->dlc);
775 }
776
777 rfcomm_dev_put(dev);
778}
779
780static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
781{
782 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
783 struct rfcomm_dlc *dlc = dev->dlc;
784 struct sk_buff *skb;
785 int err = 0, sent = 0, size;
786
787 BT_DBG("tty %p count %d", tty, count);
788
789 while (count) {
790 size = min_t(uint, count, dlc->mtu);
791
792 skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 if (!skb)
795 break;
796
797 skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
798
799 memcpy(skb_put(skb, size), buf + sent, size);
800
801 if ((err = rfcomm_dlc_send(dlc, skb)) < 0) {
802 kfree_skb(skb);
803 break;
804 }
805
806 sent += size;
807 count -= size;
808 }
809
810 return sent ? sent : err;
811}
812
813static int rfcomm_tty_write_room(struct tty_struct *tty)
814{
815 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
816 int room;
817
818 BT_DBG("tty %p", tty);
819
Marcel Holtmannb6e557f2007-01-08 02:16:27 +0100820 if (!dev || !dev->dlc)
821 return 0;
822
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc);
824 if (room < 0)
825 room = 0;
Marcel Holtmannb6e557f2007-01-08 02:16:27 +0100826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 return room;
828}
829
830static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
831{
832 BT_DBG("tty %p cmd 0x%02x", tty, cmd);
833
834 switch (cmd) {
835 case TCGETS:
836 BT_DBG("TCGETS is not supported");
837 return -ENOIOCTLCMD;
838
839 case TCSETS:
840 BT_DBG("TCSETS is not supported");
841 return -ENOIOCTLCMD;
842
843 case TIOCMIWAIT:
844 BT_DBG("TIOCMIWAIT");
845 break;
846
847 case TIOCGICOUNT:
848 BT_DBG("TIOCGICOUNT");
849 break;
850
851 case TIOCGSERIAL:
852 BT_ERR("TIOCGSERIAL is not supported");
853 return -ENOIOCTLCMD;
854
855 case TIOCSSERIAL:
856 BT_ERR("TIOCSSERIAL is not supported");
857 return -ENOIOCTLCMD;
858
859 case TIOCSERGSTRUCT:
860 BT_ERR("TIOCSERGSTRUCT is not supported");
861 return -ENOIOCTLCMD;
862
863 case TIOCSERGETLSR:
864 BT_ERR("TIOCSERGETLSR is not supported");
865 return -ENOIOCTLCMD;
866
867 case TIOCSERCONFIG:
868 BT_ERR("TIOCSERCONFIG is not supported");
869 return -ENOIOCTLCMD;
870
871 default:
872 return -ENOIOCTLCMD; /* ioctls which we must ignore */
873
874 }
875
876 return -ENOIOCTLCMD;
877}
878
Alan Cox606d0992006-12-08 02:38:45 -0800879static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880{
Alan Cox606d0992006-12-08 02:38:45 -0800881 struct ktermios *new = tty->termios;
J. Suter3a5e9032005-08-09 20:28:46 -0700882 int old_baud_rate = tty_termios_baud_rate(old);
883 int new_baud_rate = tty_termios_baud_rate(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
J. Suter3a5e9032005-08-09 20:28:46 -0700885 u8 baud, data_bits, stop_bits, parity, x_on, x_off;
886 u16 changes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
J. Suter3a5e9032005-08-09 20:28:46 -0700888 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
889
890 BT_DBG("tty %p termios %p", tty, old);
891
Marcel Holtmannff2d3672006-11-18 22:14:42 +0100892 if (!dev || !dev->dlc || !dev->dlc->session)
Marcel Holtmanncb19d9e2006-10-15 17:31:10 +0200893 return;
894
J. Suter3a5e9032005-08-09 20:28:46 -0700895 /* Handle turning off CRTSCTS */
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900896 if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS))
J. Suter3a5e9032005-08-09 20:28:46 -0700897 BT_DBG("Turning off CRTSCTS unsupported");
898
899 /* Parity on/off and when on, odd/even */
900 if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) ||
901 ((old->c_cflag & PARODD) != (new->c_cflag & PARODD)) ) {
902 changes |= RFCOMM_RPN_PM_PARITY;
903 BT_DBG("Parity change detected.");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 }
J. Suter3a5e9032005-08-09 20:28:46 -0700905
906 /* Mark and space parity are not supported! */
907 if (new->c_cflag & PARENB) {
908 if (new->c_cflag & PARODD) {
909 BT_DBG("Parity is ODD");
910 parity = RFCOMM_RPN_PARITY_ODD;
911 } else {
912 BT_DBG("Parity is EVEN");
913 parity = RFCOMM_RPN_PARITY_EVEN;
914 }
915 } else {
916 BT_DBG("Parity is OFF");
917 parity = RFCOMM_RPN_PARITY_NONE;
918 }
919
920 /* Setting the x_on / x_off characters */
921 if (old->c_cc[VSTOP] != new->c_cc[VSTOP]) {
922 BT_DBG("XOFF custom");
923 x_on = new->c_cc[VSTOP];
924 changes |= RFCOMM_RPN_PM_XON;
925 } else {
926 BT_DBG("XOFF default");
927 x_on = RFCOMM_RPN_XON_CHAR;
928 }
929
930 if (old->c_cc[VSTART] != new->c_cc[VSTART]) {
931 BT_DBG("XON custom");
932 x_off = new->c_cc[VSTART];
933 changes |= RFCOMM_RPN_PM_XOFF;
934 } else {
935 BT_DBG("XON default");
936 x_off = RFCOMM_RPN_XOFF_CHAR;
937 }
938
939 /* Handle setting of stop bits */
940 if ((old->c_cflag & CSTOPB) != (new->c_cflag & CSTOPB))
941 changes |= RFCOMM_RPN_PM_STOP;
942
943 /* POSIX does not support 1.5 stop bits and RFCOMM does not
944 * support 2 stop bits. So a request for 2 stop bits gets
945 * translated to 1.5 stop bits */
946 if (new->c_cflag & CSTOPB) {
947 stop_bits = RFCOMM_RPN_STOP_15;
948 } else {
949 stop_bits = RFCOMM_RPN_STOP_1;
950 }
951
952 /* Handle number of data bits [5-8] */
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900953 if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE))
J. Suter3a5e9032005-08-09 20:28:46 -0700954 changes |= RFCOMM_RPN_PM_DATA;
955
956 switch (new->c_cflag & CSIZE) {
957 case CS5:
958 data_bits = RFCOMM_RPN_DATA_5;
959 break;
960 case CS6:
961 data_bits = RFCOMM_RPN_DATA_6;
962 break;
963 case CS7:
964 data_bits = RFCOMM_RPN_DATA_7;
965 break;
966 case CS8:
967 data_bits = RFCOMM_RPN_DATA_8;
968 break;
969 default:
970 data_bits = RFCOMM_RPN_DATA_8;
971 break;
972 }
973
974 /* Handle baudrate settings */
975 if (old_baud_rate != new_baud_rate)
976 changes |= RFCOMM_RPN_PM_BITRATE;
977
978 switch (new_baud_rate) {
979 case 2400:
980 baud = RFCOMM_RPN_BR_2400;
981 break;
982 case 4800:
983 baud = RFCOMM_RPN_BR_4800;
984 break;
985 case 7200:
986 baud = RFCOMM_RPN_BR_7200;
987 break;
988 case 9600:
989 baud = RFCOMM_RPN_BR_9600;
990 break;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900991 case 19200:
J. Suter3a5e9032005-08-09 20:28:46 -0700992 baud = RFCOMM_RPN_BR_19200;
993 break;
994 case 38400:
995 baud = RFCOMM_RPN_BR_38400;
996 break;
997 case 57600:
998 baud = RFCOMM_RPN_BR_57600;
999 break;
1000 case 115200:
1001 baud = RFCOMM_RPN_BR_115200;
1002 break;
1003 case 230400:
1004 baud = RFCOMM_RPN_BR_230400;
1005 break;
1006 default:
1007 /* 9600 is standard accordinag to the RFCOMM specification */
1008 baud = RFCOMM_RPN_BR_9600;
1009 break;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001010
J. Suter3a5e9032005-08-09 20:28:46 -07001011 }
1012
1013 if (changes)
1014 rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud,
1015 data_bits, stop_bits, parity,
1016 RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
1017
1018 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019}
1020
1021static void rfcomm_tty_throttle(struct tty_struct *tty)
1022{
1023 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1024
1025 BT_DBG("tty %p dev %p", tty, dev);
J. Suter3a5e9032005-08-09 20:28:46 -07001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 rfcomm_dlc_throttle(dev->dlc);
1028}
1029
1030static void rfcomm_tty_unthrottle(struct tty_struct *tty)
1031{
1032 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1033
1034 BT_DBG("tty %p dev %p", tty, dev);
J. Suter3a5e9032005-08-09 20:28:46 -07001035
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 rfcomm_dlc_unthrottle(dev->dlc);
1037}
1038
1039static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty)
1040{
1041 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
1043 BT_DBG("tty %p dev %p", tty, dev);
1044
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001045 if (!dev || !dev->dlc)
1046 return 0;
1047
1048 if (!skb_queue_empty(&dev->dlc->tx_queue))
1049 return dev->dlc->mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051 return 0;
1052}
1053
1054static void rfcomm_tty_flush_buffer(struct tty_struct *tty)
1055{
1056 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
1058 BT_DBG("tty %p dev %p", tty, dev);
1059
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001060 if (!dev || !dev->dlc)
1061 return;
1062
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 skb_queue_purge(&dev->dlc->tx_queue);
1064
1065 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)
1066 tty->ldisc.write_wakeup(tty);
1067}
1068
1069static void rfcomm_tty_send_xchar(struct tty_struct *tty, char ch)
1070{
1071 BT_DBG("tty %p ch %c", tty, ch);
1072}
1073
1074static void rfcomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
1075{
1076 BT_DBG("tty %p timeout %d", tty, timeout);
1077}
1078
1079static void rfcomm_tty_hangup(struct tty_struct *tty)
1080{
1081 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
1083 BT_DBG("tty %p dev %p", tty, dev);
1084
Marcel Holtmannb6e557f2007-01-08 02:16:27 +01001085 if (!dev)
1086 return;
1087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 rfcomm_tty_flush_buffer(tty);
1089
Marcel Holtmann77f2a452007-05-05 00:36:10 +02001090 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
1091 if (rfcomm_dev_get(dev->id) == NULL)
1092 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 rfcomm_dev_del(dev);
Marcel Holtmann77f2a452007-05-05 00:36:10 +02001094 rfcomm_dev_put(dev);
1095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096}
1097
1098static int rfcomm_tty_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *unused)
1099{
1100 return 0;
1101}
1102
1103static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp)
1104{
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001105 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
1107 BT_DBG("tty %p dev %p", tty, dev);
1108
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001109 return dev->modem_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110}
1111
1112static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear)
1113{
J. Suter3a5e9032005-08-09 20:28:46 -07001114 struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
1115 struct rfcomm_dlc *dlc = dev->dlc;
1116 u8 v24_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
1118 BT_DBG("tty %p dev %p set 0x%02x clear 0x%02x", tty, dev, set, clear);
1119
J. Suter3a5e9032005-08-09 20:28:46 -07001120 rfcomm_dlc_get_modem_status(dlc, &v24_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
J. Suter3a5e9032005-08-09 20:28:46 -07001122 if (set & TIOCM_DSR || set & TIOCM_DTR)
1123 v24_sig |= RFCOMM_V24_RTC;
1124 if (set & TIOCM_RTS || set & TIOCM_CTS)
1125 v24_sig |= RFCOMM_V24_RTR;
1126 if (set & TIOCM_RI)
1127 v24_sig |= RFCOMM_V24_IC;
1128 if (set & TIOCM_CD)
1129 v24_sig |= RFCOMM_V24_DV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
J. Suter3a5e9032005-08-09 20:28:46 -07001131 if (clear & TIOCM_DSR || clear & TIOCM_DTR)
1132 v24_sig &= ~RFCOMM_V24_RTC;
1133 if (clear & TIOCM_RTS || clear & TIOCM_CTS)
1134 v24_sig &= ~RFCOMM_V24_RTR;
1135 if (clear & TIOCM_RI)
1136 v24_sig &= ~RFCOMM_V24_IC;
1137 if (clear & TIOCM_CD)
1138 v24_sig &= ~RFCOMM_V24_DV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
J. Suter3a5e9032005-08-09 20:28:46 -07001140 rfcomm_dlc_set_modem_status(dlc, v24_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
J. Suter3a5e9032005-08-09 20:28:46 -07001142 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143}
1144
1145/* ---- TTY structure ---- */
1146
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001147static const struct tty_operations rfcomm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 .open = rfcomm_tty_open,
1149 .close = rfcomm_tty_close,
1150 .write = rfcomm_tty_write,
1151 .write_room = rfcomm_tty_write_room,
1152 .chars_in_buffer = rfcomm_tty_chars_in_buffer,
1153 .flush_buffer = rfcomm_tty_flush_buffer,
1154 .ioctl = rfcomm_tty_ioctl,
1155 .throttle = rfcomm_tty_throttle,
1156 .unthrottle = rfcomm_tty_unthrottle,
1157 .set_termios = rfcomm_tty_set_termios,
1158 .send_xchar = rfcomm_tty_send_xchar,
1159 .hangup = rfcomm_tty_hangup,
1160 .wait_until_sent = rfcomm_tty_wait_until_sent,
1161 .read_proc = rfcomm_tty_read_proc,
1162 .tiocmget = rfcomm_tty_tiocmget,
1163 .tiocmset = rfcomm_tty_tiocmset,
1164};
1165
1166int rfcomm_init_ttys(void)
1167{
1168 rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
1169 if (!rfcomm_tty_driver)
1170 return -1;
1171
1172 rfcomm_tty_driver->owner = THIS_MODULE;
1173 rfcomm_tty_driver->driver_name = "rfcomm";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 rfcomm_tty_driver->name = "rfcomm";
1175 rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR;
1176 rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR;
1177 rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1178 rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001179 rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 rfcomm_tty_driver->init_termios = tty_std_termios;
1181 rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Marcel Holtmannca37bdd2008-07-14 20:13:52 +02001182 rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
1184
1185 if (tty_register_driver(rfcomm_tty_driver)) {
1186 BT_ERR("Can't register RFCOMM TTY driver");
1187 put_tty_driver(rfcomm_tty_driver);
1188 return -1;
1189 }
1190
1191 BT_INFO("RFCOMM TTY layer initialized");
1192
1193 return 0;
1194}
1195
1196void rfcomm_cleanup_ttys(void)
1197{
1198 tty_unregister_driver(rfcomm_tty_driver);
1199 put_tty_driver(rfcomm_tty_driver);
1200}