Blame view

drivers/bluetooth/hci_ldisc.c 12.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   *
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   *  Bluetooth HCI UART driver
   *
   *  Copyright (C) 2000-2001  Qualcomm Incorporated
   *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
   *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
   *
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or
   *  (at your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; if not, write to the Free Software
   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
  #include <linux/module.h>
  
  #include <linux/kernel.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  #include <linux/types.h>
  #include <linux/fcntl.h>
  #include <linux/interrupt.h>
  #include <linux/ptrace.h>
  #include <linux/poll.h>
  
  #include <linux/slab.h>
  #include <linux/tty.h>
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/signal.h>
  #include <linux/ioctl.h>
  #include <linux/skbuff.h>
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
  
  #include "hci_uart.h"
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
48
  #define VERSION "2.2"
90ab5ee94   Rusty Russell   module_param: mak...
49
  static bool reset = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
57
58
59
60
61
  
  static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
  
  int hci_uart_register_proto(struct hci_uart_proto *p)
  {
  	if (p->id >= HCI_UART_MAX_PROTO)
  		return -EINVAL;
  
  	if (hup[p->id])
  		return -EEXIST;
  
  	hup[p->id] = p;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
62

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
68
69
70
71
72
73
74
  	return 0;
  }
  
  int hci_uart_unregister_proto(struct hci_uart_proto *p)
  {
  	if (p->id >= HCI_UART_MAX_PROTO)
  		return -EINVAL;
  
  	if (!hup[p->id])
  		return -EINVAL;
  
  	hup[p->id] = NULL;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
75

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
80
81
82
  	return 0;
  }
  
  static struct hci_uart_proto *hci_uart_get_proto(unsigned int id)
  {
  	if (id >= HCI_UART_MAX_PROTO)
  		return NULL;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
83

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
89
  	return hup[id];
  }
  
  static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
  {
  	struct hci_dev *hdev = hu->hdev;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
90

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
97
98
99
100
101
  	/* Update HCI stat counters */
  	switch (pkt_type) {
  	case HCI_COMMAND_PKT:
  		hdev->stat.cmd_tx++;
  		break;
  
  	case HCI_ACLDATA_PKT:
  		hdev->stat.acl_tx++;
  		break;
  
  	case HCI_SCODATA_PKT:
7f8f2729c   Karl Beldan   Bluetooth: hci_ua...
102
  		hdev->stat.sco_tx++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
107
108
109
  		break;
  	}
  }
  
  static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
  {
  	struct sk_buff *skb = hu->tx_skb;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
110

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
  	if (!skb)
  		skb = hu->proto->dequeue(hu);
  	else
  		hu->tx_skb = NULL;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
115

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
121
122
123
  	return skb;
  }
  
  int hci_uart_tx_wakeup(struct hci_uart *hu)
  {
  	struct tty_struct *tty = hu->tty;
  	struct hci_dev *hdev = hu->hdev;
  	struct sk_buff *skb;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
124

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
129
130
131
132
133
134
135
136
  	if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
  		set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
  		return 0;
  	}
  
  	BT_DBG("");
  
  restart:
  	clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
  
  	while ((skb = hci_uart_dequeue(hu))) {
  		int len;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
137

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
f34d7a5b7   Alan Cox   tty: The big oper...
139
  		len = tty->ops->write(tty, skb->data, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
  		hdev->stat.byte_tx += len;
  
  		skb_pull(skb, len);
  		if (skb->len) {
  			hu->tx_skb = skb;
  			break;
  		}
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
147

0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
148
  		hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  		kfree_skb(skb);
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
150
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  	if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
  		goto restart;
  
  	clear_bit(HCI_UART_SENDING, &hu->tx_state);
  	return 0;
  }
  
  /* ------- Interface to HCI layer ------ */
  /* Initialize device */
  static int hci_uart_open(struct hci_dev *hdev)
  {
  	BT_DBG("%s %p", hdev->name, hdev);
  
  	/* Nothing to do for UART driver */
  
  	set_bit(HCI_RUNNING, &hdev->flags);
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
167

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  	return 0;
  }
  
  /* Reset device */
  static int hci_uart_flush(struct hci_dev *hdev)
  {
  	struct hci_uart *hu  = (struct hci_uart *) hdev->driver_data;
  	struct tty_struct *tty = hu->tty;
  
  	BT_DBG("hdev %p tty %p", hdev, tty);
  
  	if (hu->tx_skb) {
  		kfree_skb(hu->tx_skb); hu->tx_skb = NULL;
  	}
  
  	/* Flush any pending characters in the driver and discipline. */
  	tty_ldisc_flush(tty);
f34d7a5b7   Alan Cox   tty: The big oper...
185
  	tty_driver_flush_buffer(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  
  	if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
  		hu->proto->flush(hu);
  
  	return 0;
  }
  
  /* Close device */
  static int hci_uart_close(struct hci_dev *hdev)
  {
  	BT_DBG("hdev %p", hdev);
  
  	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
  		return 0;
  
  	hci_uart_flush(hdev);
3611f4d2a   David Newall   hci_ldisc: fix nu...
202
  	hdev->flush = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
205
206
207
208
209
  	return 0;
  }
  
  /* Send frames from HCI layer */
  static int hci_uart_send_frame(struct sk_buff *skb)
  {
  	struct hci_dev* hdev = (struct hci_dev *) skb->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
  	struct hci_uart *hu;
  
  	if (!hdev) {
af901ca18   AndrĂ© Goddard Rosa   tree-wide: fix as...
213
  		BT_ERR("Frame for unknown device (hdev=NULL)");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
218
219
220
  		return -ENODEV;
  	}
  
  	if (!test_bit(HCI_RUNNING, &hdev->flags))
  		return -EBUSY;
  
  	hu = (struct hci_uart *) hdev->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221

0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
222
  	BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
  
  	hu->proto->enqueue(hu, skb);
  
  	hci_uart_tx_wakeup(hu);
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
227

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
231
232
  	return 0;
  }
  
  static void hci_uart_destruct(struct hci_dev *hdev)
  {
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
233
234
  	if (!hdev)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  
  	BT_DBG("%s", hdev->name);
7785162cf   Marcel Holtmann   [Bluetooth] Code ...
237
  	kfree(hdev->driver_data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  }
  
  /* ------ LDISC part ------ */
  /* hci_uart_tty_open
   * 
   *     Called when line discipline changed to HCI_UART.
   *
   * Arguments:
   *     tty    pointer to tty info structure
   * Return Value:    
   *     0 if success, otherwise error code
   */
  static int hci_uart_tty_open(struct tty_struct *tty)
  {
  	struct hci_uart *hu = (void *) tty->disc_data;
  
  	BT_DBG("tty %p", tty);
c19483cc5   Alan Cox   bluetooth: Fix mi...
255
256
  	/* FIXME: This btw is bogus, nothing requires the old ldisc to clear
  	   the pointer */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
  	if (hu)
  		return -EEXIST;
c19483cc5   Alan Cox   bluetooth: Fix mi...
259
260
261
262
  	/* Error if the tty has no write op instead of leaving an exploitable
  	   hole */
  	if (tty->ops->write == NULL)
  		return -EOPNOTSUPP;
089b1dbbd   Deepak Saxena   [PATCH] bluetooth...
263
  	if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
7785162cf   Marcel Holtmann   [Bluetooth] Code ...
264
  		BT_ERR("Can't allocate control structure");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
  		return -ENFILE;
  	}
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
267

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
  	tty->disc_data = hu;
  	hu->tty = tty;
33f0f88f1   Alan Cox   [PATCH] TTY layer...
270
  	tty->receive_room = 65536;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
274
  
  	spin_lock_init(&hu->rx_lock);
  
  	/* Flush any pending characters in the driver and line discipline. */
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
275

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
  	/* FIXME: why is this needed. Note don't use ldisc_ref here as the
  	   open path is before the ldisc is referencable */
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
278

c65c9bc3e   Alan Cox   tty: rewrite the ...
279
280
  	if (tty->ldisc->ops->flush_buffer)
  		tty->ldisc->ops->flush_buffer(tty);
f34d7a5b7   Alan Cox   tty: The big oper...
281
  	tty_driver_flush_buffer(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
  
  	return 0;
  }
  
  /* hci_uart_tty_close()
   *
   *    Called when the line discipline is changed to something
   *    else, the tty is closed, or the tty detects a hangup.
   */
  static void hci_uart_tty_close(struct tty_struct *tty)
  {
  	struct hci_uart *hu = (void *)tty->disc_data;
  
  	BT_DBG("tty %p", tty);
  
  	/* Detach from the tty */
  	tty->disc_data = NULL;
  
  	if (hu) {
  		struct hci_dev *hdev = hu->hdev;
22ad42033   Marcel Holtmann   [Bluetooth] Fix N...
302
303
304
  
  		if (hdev)
  			hci_uart_close(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
307
  
  		if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
  			hu->proto->close(hu);
d9319560b   Jun Nie   Bluetooth: add NU...
308
309
310
311
  			if (hdev) {
  				hci_unregister_dev(hdev);
  				hci_free_dev(hdev);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  		}
  	}
  }
  
  /* hci_uart_tty_wakeup()
   *
   *    Callback for transmit wakeup. Called when low level
   *    device driver can accept more send data.
   *
   * Arguments:        tty    pointer to associated tty instance data
   * Return Value:    None
   */
  static void hci_uart_tty_wakeup(struct tty_struct *tty)
  {
  	struct hci_uart *hu = (void *)tty->disc_data;
  
  	BT_DBG("");
  
  	if (!hu)
  		return;
  
  	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
  
  	if (tty != hu->tty)
  		return;
  
  	if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
  		hci_uart_tx_wakeup(hu);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
345
346
347
348
349
350
  /* hci_uart_tty_receive()
   * 
   *     Called by tty low level driver when receive data is
   *     available.
   *     
   * Arguments:  tty          pointer to tty isntance data
   *             data         pointer to received data
   *             flags        pointer to flags for data
   *             count        count of received data in bytes
   *     
55db4c64e   Linus Torvalds   Revert "tty: make...
351
   * Return Value:    None
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
   */
55db4c64e   Linus Torvalds   Revert "tty: make...
353
  static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
  {
  	struct hci_uart *hu = (void *)tty->disc_data;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
356

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  	if (!hu || tty != hu->tty)
55db4c64e   Linus Torvalds   Revert "tty: make...
358
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
  
  	if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
55db4c64e   Linus Torvalds   Revert "tty: make...
361
  		return;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
362

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
  	spin_lock(&hu->rx_lock);
55db4c64e   Linus Torvalds   Revert "tty: make...
364
365
  	hu->proto->recv(hu, (void *) data, count);
  	hu->hdev->stat.byte_rx += count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  	spin_unlock(&hu->rx_lock);
39c2e60f8   Alan Cox   tty: add throttle...
367
  	tty_unthrottle(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  }
  
  static int hci_uart_register_dev(struct hci_uart *hu)
  {
  	struct hci_dev *hdev;
  
  	BT_DBG("");
  
  	/* Initialize and register HCI device */
  	hdev = hci_alloc_dev();
  	if (!hdev) {
  		BT_ERR("Can't allocate HCI device");
  		return -ENOMEM;
  	}
  
  	hu->hdev = hdev;
c13854cef   Marcel Holtmann   Bluetooth: Conver...
384
  	hdev->bus = HCI_UART;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
387
388
389
390
391
  	hdev->driver_data = hu;
  
  	hdev->open  = hci_uart_open;
  	hdev->close = hci_uart_close;
  	hdev->flush = hci_uart_flush;
  	hdev->send  = hci_uart_send_frame;
  	hdev->destruct = hci_uart_destruct;
7f4b2b04c   Andrei Warkentin   Bluetooth: Make h...
392
  	hdev->parent = hu->tty->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
  
  	hdev->owner = THIS_MODULE;
7a9d40205   Marcel Holtmann   Bluetooth: Send H...
395
396
  	if (!reset)
  		set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397

63c7d09cd   Johan Hedberg   Bluetooth: Add HC...
398
399
  	if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
  		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
402
403
404
405
406
407
408
409
410
411
  	if (hci_register_dev(hdev) < 0) {
  		BT_ERR("Can't register HCI device");
  		hci_free_dev(hdev);
  		return -ENODEV;
  	}
  
  	return 0;
  }
  
  static int hci_uart_set_proto(struct hci_uart *hu, int id)
  {
  	struct hci_uart_proto *p;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
412
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  	p = hci_uart_get_proto(id);
  	if (!p)
  		return -EPROTONOSUPPORT;
  
  	err = p->open(hu);
  	if (err)
  		return err;
  
  	hu->proto = p;
  
  	err = hci_uart_register_dev(hu);
  	if (err) {
  		p->close(hu);
  		return err;
  	}
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
428

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  	return 0;
  }
  
  /* hci_uart_tty_ioctl()
   *
   *    Process IOCTL system call for the tty device.
   *
   * Arguments:
   *
   *    tty        pointer to tty instance data
   *    file       pointer to open file object for device
   *    cmd        IOCTL command code
   *    arg        argument for IOCTL call (cmd dependent)
   *
   * Return Value:    Command dependent
   */
  static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
446
  					unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
  {
  	struct hci_uart *hu = (void *)tty->disc_data;
  	int err = 0;
  
  	BT_DBG("");
  
  	/* Verify the status of the device */
  	if (!hu)
  		return -EBADF;
  
  	switch (cmd) {
  	case HCIUARTSETPROTO:
  		if (!test_and_set_bit(HCI_UART_PROTO_SET, &hu->flags)) {
  			err = hci_uart_set_proto(hu, arg);
  			if (err) {
  				clear_bit(HCI_UART_PROTO_SET, &hu->flags);
  				return err;
  			}
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
465
  		} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
  			return -EBUSY;
c33be3c36   Marcel Holtmann   [Bluetooth] Fix u...
467
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
472
  
  	case HCIUARTGETPROTO:
  		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
  			return hu->proto->id;
  		return -EUNATCH;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
473

d21587446   Marcel Holtmann   [Bluetooth] Add H...
474
475
476
477
  	case HCIUARTGETDEVICE:
  		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
  			return hu->hdev->id;
  		return -EUNATCH;
63c7d09cd   Johan Hedberg   Bluetooth: Add HC...
478
479
480
481
482
483
484
485
  	case HCIUARTSETFLAGS:
  		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
  			return -EBUSY;
  		hu->hdev_flags = arg;
  		break;
  
  	case HCIUARTGETFLAGS:
  		return hu->hdev_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
  	default:
47afa7a5a   Alan Cox   tty: some ICANON ...
487
  		err = n_tty_ioctl_helper(tty, file, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
489
490
491
492
493
494
495
496
  		break;
  	};
  
  	return err;
  }
  
  /*
   * We don't provide read/write/poll interface for user space.
   */
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
497
498
  static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
  					unsigned char __user *buf, size_t nr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
501
  {
  	return 0;
  }
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
502
503
504
  
  static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file,
  					const unsigned char *data, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
507
  {
  	return 0;
  }
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
508
509
510
  
  static unsigned int hci_uart_tty_poll(struct tty_struct *tty,
  					struct file *filp, poll_table *wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
  {
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
  static int __init hci_uart_init(void)
  {
a352def21   Alan Cox   tty: Ldisc revamp
516
  	static struct tty_ldisc_ops hci_uart_ldisc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
519
520
521
522
523
  	int err;
  
  	BT_INFO("HCI UART driver ver %s", VERSION);
  
  	/* Register the tty discipline */
  
  	memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
524
525
526
527
528
529
530
531
  	hci_uart_ldisc.magic		= TTY_LDISC_MAGIC;
  	hci_uart_ldisc.name		= "n_hci";
  	hci_uart_ldisc.open		= hci_uart_tty_open;
  	hci_uart_ldisc.close		= hci_uart_tty_close;
  	hci_uart_ldisc.read		= hci_uart_tty_read;
  	hci_uart_ldisc.write		= hci_uart_tty_write;
  	hci_uart_ldisc.ioctl		= hci_uart_tty_ioctl;
  	hci_uart_ldisc.poll		= hci_uart_tty_poll;
0372a6627   Marcel Holtmann   [Bluetooth] Clean...
532
533
534
  	hci_uart_ldisc.receive_buf	= hci_uart_tty_receive;
  	hci_uart_ldisc.write_wakeup	= hci_uart_tty_wakeup;
  	hci_uart_ldisc.owner		= THIS_MODULE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
540
541
542
543
544
545
546
  
  	if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
  		BT_ERR("HCI line discipline registration failed. (%d)", err);
  		return err;
  	}
  
  #ifdef CONFIG_BT_HCIUART_H4
  	h4_init();
  #endif
  #ifdef CONFIG_BT_HCIUART_BCSP
  	bcsp_init();
  #endif
166d2f6a4   Ohad Ben-Cohen   [Bluetooth] Add U...
547
548
549
  #ifdef CONFIG_BT_HCIUART_LL
  	ll_init();
  #endif
b3190df62   Suraj Sumangala   Bluetooth: Suppor...
550
551
552
  #ifdef CONFIG_BT_HCIUART_ATH3K
  	ath_init();
  #endif
166d2f6a4   Ohad Ben-Cohen   [Bluetooth] Add U...
553

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
556
557
558
559
560
561
562
563
564
565
566
  	return 0;
  }
  
  static void __exit hci_uart_exit(void)
  {
  	int err;
  
  #ifdef CONFIG_BT_HCIUART_H4
  	h4_deinit();
  #endif
  #ifdef CONFIG_BT_HCIUART_BCSP
  	bcsp_deinit();
  #endif
166d2f6a4   Ohad Ben-Cohen   [Bluetooth] Add U...
567
568
569
  #ifdef CONFIG_BT_HCIUART_LL
  	ll_deinit();
  #endif
b3190df62   Suraj Sumangala   Bluetooth: Suppor...
570
571
572
  #ifdef CONFIG_BT_HCIUART_ATH3K
  	ath_deinit();
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
574
  
  	/* Release tty registration of line discipline */
64ccd715d   Alexey Dobriyan   [PATCH] Convert u...
575
  	if ((err = tty_unregister_ldisc(N_HCI)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
578
579
580
581
582
583
  		BT_ERR("Can't unregister HCI line discipline (%d)", err);
  }
  
  module_init(hci_uart_init);
  module_exit(hci_uart_exit);
  
  module_param(reset, bool, 0644);
  MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
63fbd24e5   Marcel Holtmann   [Bluetooth] Conso...
584
  MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
588
  MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);
  MODULE_VERSION(VERSION);
  MODULE_LICENSE("GPL");
  MODULE_ALIAS_LDISC(N_HCI);