aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/hci_ldisc.c
diff options
context:
space:
mode:
authorIlya Faenson <ifaenson@broadcom.com>2015-06-17 17:30:56 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-06-17 17:44:49 -0400
commit2a973dfada2bcd61e1ce31612677da1a9ecc2124 (patch)
tree76865aa13660f248099d54918cf69242855ba3ce /drivers/bluetooth/hci_ldisc.c
parent89e4042861772a89fc54ce517255c3a38ba58ac1 (diff)
Bluetooth: hci_uart: Add new line discipline enhancements
Added the ability to flow control the UART, improved the UART baud rate setting, transferred the speeds into line discipline from the protocol and introduced the tty init function. Signed-off-by: Ilya Faenson <ifaenson@broadcom.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth/hci_ldisc.c')
-rw-r--r--drivers/bluetooth/hci_ldisc.c108
1 files changed, 102 insertions, 6 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index ac87346ce9d7..590bd8e66bfb 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -266,6 +266,85 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
266 return 0; 266 return 0;
267} 267}
268 268
269/* Flow control or un-flow control the device */
270void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
271{
272 struct tty_struct *tty = hu->tty;
273 struct ktermios ktermios;
274 int status;
275 unsigned int set = 0;
276 unsigned int clear = 0;
277
278 if (enable) {
279 /* Disable hardware flow control */
280 ktermios = tty->termios;
281 ktermios.c_cflag &= ~CRTSCTS;
282 status = tty_set_termios(tty, &ktermios);
283 BT_DBG("Disabling hardware flow control: %s",
284 status ? "failed" : "success");
285
286 /* Clear RTS to prevent the device from sending */
287 /* Most UARTs need OUT2 to enable interrupts */
288 status = tty->driver->ops->tiocmget(tty);
289 BT_DBG("Current tiocm 0x%x", status);
290
291 set &= ~(TIOCM_OUT2 | TIOCM_RTS);
292 clear = ~set;
293 set &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
294 TIOCM_OUT2 | TIOCM_LOOP;
295 clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
296 TIOCM_OUT2 | TIOCM_LOOP;
297 status = tty->driver->ops->tiocmset(tty, set, clear);
298 BT_DBG("Clearing RTS: %s", status ? "failed" : "success");
299 } else {
300 /* Set RTS to allow the device to send again */
301 status = tty->driver->ops->tiocmget(tty);
302 BT_DBG("Current tiocm 0x%x", status);
303
304 set |= (TIOCM_OUT2 | TIOCM_RTS);
305 clear = ~set;
306 set &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
307 TIOCM_OUT2 | TIOCM_LOOP;
308 clear &= TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 |
309 TIOCM_OUT2 | TIOCM_LOOP;
310 status = tty->driver->ops->tiocmset(tty, set, clear);
311 BT_DBG("Setting RTS: %s", status ? "failed" : "success");
312
313 /* Re-enable hardware flow control */
314 ktermios = tty->termios;
315 ktermios.c_cflag |= CRTSCTS;
316 status = tty_set_termios(tty, &ktermios);
317 BT_DBG("Enabling hardware flow control: %s",
318 status ? "failed" : "success");
319 }
320}
321
322void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
323 unsigned int oper_speed)
324{
325 hu->init_speed = init_speed;
326 hu->oper_speed = oper_speed;
327}
328
329void hci_uart_init_tty(struct hci_uart *hu)
330{
331 struct tty_struct *tty = hu->tty;
332 struct ktermios ktermios;
333
334 /* Bring the UART into a known 8 bits no parity hw fc state */
335 ktermios = tty->termios;
336 ktermios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
337 INLCR | IGNCR | ICRNL | IXON);
338 ktermios.c_oflag &= ~OPOST;
339 ktermios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
340 ktermios.c_cflag &= ~(CSIZE | PARENB);
341 ktermios.c_cflag |= CS8;
342 ktermios.c_cflag |= CRTSCTS;
343
344 /* tty_set_termios() return not checked as it is always 0 */
345 tty_set_termios(tty, &ktermios);
346}
347
269void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed) 348void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed)
270{ 349{
271 struct tty_struct *tty = hu->tty; 350 struct tty_struct *tty = hu->tty;
@@ -273,13 +352,13 @@ void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed)
273 352
274 ktermios = tty->termios; 353 ktermios = tty->termios;
275 ktermios.c_cflag &= ~CBAUD; 354 ktermios.c_cflag &= ~CBAUD;
276 ktermios.c_cflag |= BOTHER;
277 tty_termios_encode_baud_rate(&ktermios, speed, speed); 355 tty_termios_encode_baud_rate(&ktermios, speed, speed);
278 356
279 /* tty_set_termios() return not checked as it is always 0 */ 357 /* tty_set_termios() return not checked as it is always 0 */
280 tty_set_termios(tty, &ktermios); 358 tty_set_termios(tty, &ktermios);
281 359
282 BT_DBG("%s: New tty speed: %d", hu->hdev->name, tty->termios.c_ispeed); 360 BT_DBG("%s: New tty speeds: %d/%d", hu->hdev->name,
361 tty->termios.c_ispeed, tty->termios.c_ospeed);
283} 362}
284 363
285static int hci_uart_setup(struct hci_dev *hdev) 364static int hci_uart_setup(struct hci_dev *hdev)
@@ -287,15 +366,32 @@ static int hci_uart_setup(struct hci_dev *hdev)
287 struct hci_uart *hu = hci_get_drvdata(hdev); 366 struct hci_uart *hu = hci_get_drvdata(hdev);
288 struct hci_rp_read_local_version *ver; 367 struct hci_rp_read_local_version *ver;
289 struct sk_buff *skb; 368 struct sk_buff *skb;
369 unsigned int speed;
290 int err; 370 int err;
291 371
372 /* Init speed if any */
292 if (hu->proto->init_speed) 373 if (hu->proto->init_speed)
293 hci_uart_set_baudrate(hu, hu->proto->init_speed); 374 speed = hu->proto->init_speed;
375 else if (hu->init_speed)
376 speed = hu->init_speed;
377 else
378 speed = 0;
379
380 if (speed)
381 hci_uart_set_baudrate(hu, speed);
382
383 /* Operational speed if any */
384 if (hu->proto->oper_speed)
385 speed = hu->proto->oper_speed;
386 else if (hu->oper_speed)
387 speed = hu->oper_speed;
388 else
389 speed = 0;
294 390
295 if (hu->proto->set_baudrate && hu->proto->oper_speed) { 391 if (hu->proto->set_baudrate && speed) {
296 err = hu->proto->set_baudrate(hu, hu->proto->oper_speed); 392 err = hu->proto->set_baudrate(hu, speed);
297 if (!err) 393 if (!err)
298 hci_uart_set_baudrate(hu, hu->proto->oper_speed); 394 hci_uart_set_baudrate(hu, speed);
299 } 395 }
300 396
301 if (hu->proto->setup) 397 if (hu->proto->setup)