cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aircable.c (4986B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * AIRcable USB Bluetooth Dongle Driver.
      4 *
      5 * Copyright (C) 2010 Johan Hovold <jhovold@gmail.com>
      6 * Copyright (C) 2006 Manuel Francisco Naranjo (naranjo.manuel@gmail.com)
      7 *
      8 * The device works as an standard CDC device, it has 2 interfaces, the first
      9 * one is for firmware access and the second is the serial one.
     10 * The protocol is very simply, there are two possibilities reading or writing.
     11 * When writing the first urb must have a Header that starts with 0x20 0x29 the
     12 * next two bytes must say how much data will be sent.
     13 * When reading the process is almost equal except that the header starts with
     14 * 0x00 0x20.
     15 *
     16 * The device simply need some stuff to understand data coming from the usb
     17 * buffer: The First and Second byte is used for a Header, the Third and Fourth
     18 * tells the  device the amount of information the package holds.
     19 * Packages are 60 bytes long Header Stuff.
     20 * When writing to the device the first two bytes of the header are 0x20 0x29
     21 * When reading the bytes are 0x00 0x20, or 0x00 0x10, there is an strange
     22 * situation, when too much data arrives to the device because it sends the data
     23 * but with out the header. I will use a simply hack to override this situation,
     24 * if there is data coming that does not contain any header, then that is data
     25 * that must go directly to the tty, as there is no documentation about if there
     26 * is any other control code, I will simply check for the first
     27 * one.
     28 *
     29 * I have taken some info from a Greg Kroah-Hartman article:
     30 * http://www.linuxjournal.com/article/6573
     31 * And from Linux Device Driver Kit CD, which is a great work, the authors taken
     32 * the work to recompile lots of information an knowledge in drivers development
     33 * and made it all available inside a cd.
     34 * URL: http://kernel.org/pub/linux/kernel/people/gregkh/ddk/
     35 *
     36 */
     37
     38#include <asm/unaligned.h>
     39#include <linux/tty.h>
     40#include <linux/slab.h>
     41#include <linux/module.h>
     42#include <linux/tty_flip.h>
     43#include <linux/usb.h>
     44#include <linux/usb/serial.h>
     45
     46/* Vendor and Product ID */
     47#define AIRCABLE_VID		0x16CA
     48#define AIRCABLE_USB_PID	0x1502
     49
     50/* Protocol Stuff */
     51#define HCI_HEADER_LENGTH	0x4
     52#define TX_HEADER_0		0x20
     53#define TX_HEADER_1		0x29
     54#define RX_HEADER_0		0x00
     55#define RX_HEADER_1		0x20
     56#define HCI_COMPLETE_FRAME	64
     57
     58/* rx_flags */
     59#define THROTTLED		0x01
     60#define ACTUALLY_THROTTLED	0x02
     61
     62#define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>, Johan Hovold <jhovold@gmail.com>"
     63#define DRIVER_DESC "AIRcable USB Driver"
     64
     65/* ID table that will be registered with USB core */
     66static const struct usb_device_id id_table[] = {
     67	{ USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) },
     68	{ },
     69};
     70MODULE_DEVICE_TABLE(usb, id_table);
     71
     72static int aircable_prepare_write_buffer(struct usb_serial_port *port,
     73						void *dest, size_t size)
     74{
     75	int count;
     76	unsigned char *buf = dest;
     77
     78	count = kfifo_out_locked(&port->write_fifo, buf + HCI_HEADER_LENGTH,
     79					size - HCI_HEADER_LENGTH, &port->lock);
     80	buf[0] = TX_HEADER_0;
     81	buf[1] = TX_HEADER_1;
     82	put_unaligned_le16(count, &buf[2]);
     83
     84	return count + HCI_HEADER_LENGTH;
     85}
     86
     87static int aircable_calc_num_ports(struct usb_serial *serial,
     88					struct usb_serial_endpoints *epds)
     89{
     90	/* Ignore the first interface, which has no bulk endpoints. */
     91	if (epds->num_bulk_out == 0) {
     92		dev_dbg(&serial->interface->dev,
     93			"ignoring interface with no bulk-out endpoints\n");
     94		return -ENODEV;
     95	}
     96
     97	return 1;
     98}
     99
    100static int aircable_process_packet(struct usb_serial_port *port,
    101		int has_headers, char *packet, int len)
    102{
    103	if (has_headers) {
    104		len -= HCI_HEADER_LENGTH;
    105		packet += HCI_HEADER_LENGTH;
    106	}
    107	if (len <= 0) {
    108		dev_dbg(&port->dev, "%s - malformed packet\n", __func__);
    109		return 0;
    110	}
    111
    112	tty_insert_flip_string(&port->port, packet, len);
    113
    114	return len;
    115}
    116
    117static void aircable_process_read_urb(struct urb *urb)
    118{
    119	struct usb_serial_port *port = urb->context;
    120	char *data = urb->transfer_buffer;
    121	int has_headers;
    122	int count;
    123	int len;
    124	int i;
    125
    126	has_headers = (urb->actual_length > 2 && data[0] == RX_HEADER_0);
    127
    128	count = 0;
    129	for (i = 0; i < urb->actual_length; i += HCI_COMPLETE_FRAME) {
    130		len = min_t(int, urb->actual_length - i, HCI_COMPLETE_FRAME);
    131		count += aircable_process_packet(port, has_headers,
    132								&data[i], len);
    133	}
    134
    135	if (count)
    136		tty_flip_buffer_push(&port->port);
    137}
    138
    139static struct usb_serial_driver aircable_device = {
    140	.driver = {
    141		.owner =	THIS_MODULE,
    142		.name =		"aircable",
    143	},
    144	.id_table = 		id_table,
    145	.bulk_out_size =	HCI_COMPLETE_FRAME,
    146	.calc_num_ports =	aircable_calc_num_ports,
    147	.process_read_urb =	aircable_process_read_urb,
    148	.prepare_write_buffer =	aircable_prepare_write_buffer,
    149	.throttle =		usb_serial_generic_throttle,
    150	.unthrottle =		usb_serial_generic_unthrottle,
    151};
    152
    153static struct usb_serial_driver * const serial_drivers[] = {
    154	&aircable_device, NULL
    155};
    156
    157module_usb_serial_driver(serial_drivers, id_table);
    158
    159MODULE_AUTHOR(DRIVER_AUTHOR);
    160MODULE_DESCRIPTION(DRIVER_DESC);
    161MODULE_LICENSE("GPL v2");