0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #include <asm/unaligned.h>
0039 #include <linux/tty.h>
0040 #include <linux/slab.h>
0041 #include <linux/module.h>
0042 #include <linux/tty_flip.h>
0043 #include <linux/usb.h>
0044 #include <linux/usb/serial.h>
0045
0046
0047 #define AIRCABLE_VID 0x16CA
0048 #define AIRCABLE_USB_PID 0x1502
0049
0050
0051 #define HCI_HEADER_LENGTH 0x4
0052 #define TX_HEADER_0 0x20
0053 #define TX_HEADER_1 0x29
0054 #define RX_HEADER_0 0x00
0055 #define RX_HEADER_1 0x20
0056 #define HCI_COMPLETE_FRAME 64
0057
0058
0059 #define THROTTLED 0x01
0060 #define ACTUALLY_THROTTLED 0x02
0061
0062 #define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>, Johan Hovold <jhovold@gmail.com>"
0063 #define DRIVER_DESC "AIRcable USB Driver"
0064
0065
0066 static const struct usb_device_id id_table[] = {
0067 { USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) },
0068 { },
0069 };
0070 MODULE_DEVICE_TABLE(usb, id_table);
0071
0072 static int aircable_prepare_write_buffer(struct usb_serial_port *port,
0073 void *dest, size_t size)
0074 {
0075 int count;
0076 unsigned char *buf = dest;
0077
0078 count = kfifo_out_locked(&port->write_fifo, buf + HCI_HEADER_LENGTH,
0079 size - HCI_HEADER_LENGTH, &port->lock);
0080 buf[0] = TX_HEADER_0;
0081 buf[1] = TX_HEADER_1;
0082 put_unaligned_le16(count, &buf[2]);
0083
0084 return count + HCI_HEADER_LENGTH;
0085 }
0086
0087 static int aircable_calc_num_ports(struct usb_serial *serial,
0088 struct usb_serial_endpoints *epds)
0089 {
0090
0091 if (epds->num_bulk_out == 0) {
0092 dev_dbg(&serial->interface->dev,
0093 "ignoring interface with no bulk-out endpoints\n");
0094 return -ENODEV;
0095 }
0096
0097 return 1;
0098 }
0099
0100 static int aircable_process_packet(struct usb_serial_port *port,
0101 int has_headers, char *packet, int len)
0102 {
0103 if (has_headers) {
0104 len -= HCI_HEADER_LENGTH;
0105 packet += HCI_HEADER_LENGTH;
0106 }
0107 if (len <= 0) {
0108 dev_dbg(&port->dev, "%s - malformed packet\n", __func__);
0109 return 0;
0110 }
0111
0112 tty_insert_flip_string(&port->port, packet, len);
0113
0114 return len;
0115 }
0116
0117 static void aircable_process_read_urb(struct urb *urb)
0118 {
0119 struct usb_serial_port *port = urb->context;
0120 char *data = urb->transfer_buffer;
0121 int has_headers;
0122 int count;
0123 int len;
0124 int i;
0125
0126 has_headers = (urb->actual_length > 2 && data[0] == RX_HEADER_0);
0127
0128 count = 0;
0129 for (i = 0; i < urb->actual_length; i += HCI_COMPLETE_FRAME) {
0130 len = min_t(int, urb->actual_length - i, HCI_COMPLETE_FRAME);
0131 count += aircable_process_packet(port, has_headers,
0132 &data[i], len);
0133 }
0134
0135 if (count)
0136 tty_flip_buffer_push(&port->port);
0137 }
0138
0139 static struct usb_serial_driver aircable_device = {
0140 .driver = {
0141 .owner = THIS_MODULE,
0142 .name = "aircable",
0143 },
0144 .id_table = id_table,
0145 .bulk_out_size = HCI_COMPLETE_FRAME,
0146 .calc_num_ports = aircable_calc_num_ports,
0147 .process_read_urb = aircable_process_read_urb,
0148 .prepare_write_buffer = aircable_prepare_write_buffer,
0149 .throttle = usb_serial_generic_throttle,
0150 .unthrottle = usb_serial_generic_unthrottle,
0151 };
0152
0153 static struct usb_serial_driver * const serial_drivers[] = {
0154 &aircable_device, NULL
0155 };
0156
0157 module_usb_serial_driver(serial_drivers, id_table);
0158
0159 MODULE_AUTHOR(DRIVER_AUTHOR);
0160 MODULE_DESCRIPTION(DRIVER_DESC);
0161 MODULE_LICENSE("GPL v2");