?? bluetty.c
字號:
return -ENODEV;
}
dbg(__FUNCTION__ " - %d byte(s)", count);
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not opened");
return -EINVAL;
}
if (count == 0) {
dbg(__FUNCTION__ " - write request of 0 bytes");
return 0;
}
if (count == 1) {
dbg(__FUNCTION__ " - write request only included type %d", buf[0]);
return 1;
}
#ifdef DEBUG
printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
for (i = 0; i < count; ++i) {
printk ("%.2x ", buf[i]);
}
printk ("\n");
#endif
if (from_user) {
temp_buffer = kmalloc (count, GFP_KERNEL);
if (temp_buffer == NULL) {
err (__FUNCTION__ "- out of memory.");
retval = -ENOMEM;
goto exit;
}
if (copy_from_user (temp_buffer, buf, count)) {
retval = -EFAULT;
goto exit;
}
current_buffer = temp_buffer;
} else {
current_buffer = buf;
}
switch (*current_buffer) {
/* First byte indicates the type of packet */
case CMD_PKT:
/* dbg(__FUNCTION__ "- Send cmd_pkt len:%d", count);*/
retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, ¤t_buffer[1], count-1);
if (retval) {
goto exit;
}
retval = count;
break;
case ACL_PKT:
current_position = current_buffer;
++current_position;
--count;
bytes_sent = 0;
while (count > 0) {
urb = NULL;
/* try to find a free urb in our list */
for (i = 0; i < NUM_BULK_URBS; ++i) {
if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
urb = bluetooth->write_urb_pool[i];
break;
}
}
if (urb == NULL) {
dbg (__FUNCTION__ " - no free urbs");
retval = bytes_sent;
goto exit;
}
buffer_size = min (count, bluetooth->bulk_out_buffer_size);
memcpy (urb->transfer_buffer, current_position, buffer_size);
/* build up our urb */
FILL_BULK_URB (urb, bluetooth->dev, usb_sndbulkpipe(bluetooth->dev, bluetooth->bulk_out_endpointAddress),
urb->transfer_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth);
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with error = %d", retval);
goto exit;
}
#ifdef BTBUGGYHARDWARE
/* A workaround for the stalled data bug */
/* May or may not be needed...*/
if (count != 0) {
udelay(500);
}
#endif
current_position += buffer_size;
bytes_sent += buffer_size;
count -= buffer_size;
}
retval = bytes_sent + 1;
break;
default :
dbg(__FUNCTION__" - unsupported (at this time) write type");
retval = -EINVAL;
break;
}
exit:
if (temp_buffer != NULL)
kfree (temp_buffer);
return retval;
}
static int bluetooth_write_room (struct tty_struct *tty)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
int room = 0;
int i;
if (!bluetooth) {
return -ENODEV;
}
dbg(__FUNCTION__);
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return -EINVAL;
}
for (i = 0; i < NUM_BULK_URBS; ++i) {
if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
room += bluetooth->bulk_out_buffer_size;
}
}
dbg(__FUNCTION__ " - returns %d", room);
return room;
}
static int bluetooth_chars_in_buffer (struct tty_struct *tty)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
int chars = 0;
int i;
if (!bluetooth) {
return -ENODEV;
}
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return -EINVAL;
}
for (i = 0; i < NUM_BULK_URBS; ++i) {
if (bluetooth->write_urb_pool[i]->status == -EINPROGRESS) {
chars += bluetooth->write_urb_pool[i]->transfer_buffer_length;
}
}
dbg (__FUNCTION__ " - returns %d", chars);
return chars;
}
static void bluetooth_throttle (struct tty_struct * tty)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
if (!bluetooth) {
return;
}
dbg(__FUNCTION__);
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
dbg(__FUNCTION__ " unsupported (at this time)");
return;
}
static void bluetooth_unthrottle (struct tty_struct * tty)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
if (!bluetooth) {
return;
}
dbg(__FUNCTION__);
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
dbg(__FUNCTION__ " unsupported (at this time)");
}
static int bluetooth_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
if (!bluetooth) {
return -ENODEV;
}
dbg(__FUNCTION__ " - cmd 0x%.4x", cmd);
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return -ENODEV;
}
/* FIXME!!! */
return -ENOIOCTLCMD;
}
static void bluetooth_set_termios (struct tty_struct *tty, struct termios * old)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
if (!bluetooth) {
return;
}
dbg(__FUNCTION__);
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
/* FIXME!!! */
return;
}
#ifdef BTBUGGYHARDWARE
void btusb_enable_bulk_read(struct tty_struct *tty){
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
int result;
if (!bluetooth) {
return;
}
dbg(__FUNCTION__);
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
if (bluetooth->read_urb) {
FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev,
usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size,
bluetooth_read_bulk_callback, bluetooth);
result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
if (result)
err (__FUNCTION__ " - failed submitting read urb, error %d", result);
}
}
void btusb_disable_bulk_read(struct tty_struct *tty){
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
if (!bluetooth) {
return;
}
dbg(__FUNCTION__);
if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length))
usb_unlink_urb(bluetooth->read_urb);
}
#endif
/*****************************************************************************
* urb callback functions
*****************************************************************************/
static void bluetooth_int_callback (struct urb *urb)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
unsigned char *data = urb->transfer_buffer;
unsigned int i;
unsigned int count = urb->actual_length;
unsigned int packet_size;
dbg(__FUNCTION__);
if (!bluetooth) {
dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
return;
}
if (urb->status) {
dbg(__FUNCTION__ " - nonzero int status received: %d", urb->status);
return;
}
if (!count) {
dbg(__FUNCTION__ " - zero length int");
return;
}
#ifdef DEBUG
if (count) {
printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count);
for (i = 0; i < count; ++i) {
printk ("%.2x ", data[i]);
}
printk ("\n");
}
#endif
#ifdef BTBUGGYHARDWARE
if ((count >= 2) && (data[0] == 0xFF) && (data[1] == 0x00)) {
data += 2;
count -= 2;
}
if (count == 0) {
urb->actual_length = 0;
return;
}
#endif
/* We add a packet type identifier to the beginning of each
HCI frame. This makes the data in the tty look like a
serial USB devices. Each HCI frame can be broken across
multiple URBs so we buffer them until we have a full hci
packet */
if (!bluetooth->int_packet_pos) {
bluetooth->int_buffer[0] = EVENT_PKT;
bluetooth->int_packet_pos++;
}
if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) {
err(__FUNCTION__ " - exceeded EVENT_BUFFER_SIZE");
bluetooth->int_packet_pos = 0;
return;
}
memcpy (&bluetooth->int_buffer[bluetooth->int_packet_pos],
urb->transfer_buffer, count);
bluetooth->int_packet_pos += count;
urb->actual_length = 0;
if (bluetooth->int_packet_pos >= EVENT_HDR_SIZE)
packet_size = bluetooth->int_buffer[2];
else
return;
if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) {
err(__FUNCTION__ " - packet was too long");
bluetooth->int_packet_pos = 0;
return;
}
if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) {
for (i = 0; i < bluetooth->int_packet_pos; ++i) {
/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */
if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(bluetooth->tty);
}
tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0);
}
tty_flip_buffer_push(bluetooth->tty);
bluetooth->int_packet_pos = 0;
}
}
static void bluetooth_ctrl_callback (struct urb *urb)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
dbg(__FUNCTION__);
if (!bluetooth) {
dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
return;
}
if (urb->status) {
dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
return;
}
}
static void bluetooth_read_bulk_callback (struct urb *urb)
{
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
unsigned char *data = urb->transfer_buffer;
unsigned int count = urb->actual_length;
unsigned int i;
unsigned int packet_size;
int result;
dbg(__FUNCTION__);
if (!bluetooth) {
dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
return;
}
if (urb->status) {
dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
if (urb->status == -ENOENT) {
dbg(__FUNCTION__ " - URB canceled, won't reschedule");
return;
}
goto exit;
}
if (!count) {
dbg(__FUNCTION__ " - zero length read bulk");
goto exit;
}
#ifdef DEBUG
if (count) {
printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count);
for (i = 0; i < count; ++i) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -