⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftdi-elan.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        return 0;}#define FTDI_ELAN_IOC_MAGIC 0xA1#define FTDI_ELAN_IOCDEBUG _IOC(_IOC_WRITE, FTDI_ELAN_IOC_MAGIC, 1, 132)static int ftdi_elan_ioctl(struct inode *inode, struct file *file,        unsigned int cmd, unsigned long arg){        switch (cmd) {        case FTDI_ELAN_IOCDEBUG:{                        char line[132];                        int size = strncpy_from_user(line,                                (const char __user *)arg, sizeof(line));                        if (size < 0) {                                return -EINVAL;                        } else {                                printk(KERN_ERR "TODO: ioctl %s\n", line);                                return 0;                        }                }        default:                return -EFAULT;        }}/*** blocking bulk reads are used to get data from the device**/static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,			      size_t count, loff_t *ppos){        char data[30 *3 + 4];        char *d = data;        int m = (sizeof(data) - 1) / 3;        int bytes_read = 0;        int retry_on_empty = 10;        int retry_on_timeout = 5;        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;        if (ftdi->disconnected > 0) {                return -ENODEV;        }        data[0] = 0;      have:if (ftdi->bulk_in_left > 0) {                if (count-- > 0) {                        char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer;                        ftdi->bulk_in_left -= 1;                        if (bytes_read < m) {                                d += sprintf(d, " %02X", 0x000000FF & *p);                        } else if (bytes_read > m) {                        } else                                d += sprintf(d, " ..");                        if (copy_to_user(buffer++, p, 1)) {                                return -EFAULT;                        } else {                                bytes_read += 1;                                goto have;                        }                } else                        return bytes_read;        }      more:if (count > 0) {                int packet_bytes = 0;                int retval = usb_bulk_msg(ftdi->udev,                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,                        &packet_bytes, msecs_to_jiffies(50));                if (packet_bytes > 2) {                        ftdi->bulk_in_left = packet_bytes - 2;                        ftdi->bulk_in_last = 1;                        goto have;                } else if (retval == -ETIMEDOUT) {                        if (retry_on_timeout-- > 0) {                                goto more;                        } else if (bytes_read > 0) {                                return bytes_read;                        } else                                return retval;                } else if (retval == 0) {                        if (retry_on_empty-- > 0) {                                goto more;                        } else                                return bytes_read;                } else                        return retval;        } else                return bytes_read;}static void ftdi_elan_write_bulk_callback(struct urb *urb){        struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;	int status = urb->status;	if (status && !(status == -ENOENT || status == -ECONNRESET ||	    status == -ESHUTDOWN)) {                dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %"                        "d\n", urb, status);        }        usb_buffer_free(urb->dev, urb->transfer_buffer_length,                urb->transfer_buffer, urb->transfer_dma);}static int fill_buffer_with_all_queued_commands(struct usb_ftdi *ftdi,        char *buf, int command_size, int total_size){        int ed_commands = 0;        int b = 0;        int I = command_size;        int i = ftdi->command_head;        while (I-- > 0) {                struct u132_command *command = &ftdi->command[COMMAND_MASK &                        i++];                int F = command->follows;                u8 *f = command->buffer;                if (command->header & 0x80) {                        ed_commands |= 1 << (0x3 & (command->header >> 5));                }                buf[b++] = command->header;                buf[b++] = (command->length >> 0) & 0x00FF;                buf[b++] = (command->length >> 8) & 0x00FF;                buf[b++] = command->address;                buf[b++] = command->width;                while (F-- > 0) {                        buf[b++] = *f++;                }        }        return ed_commands;}static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size){        int total_size = 0;        int I = command_size;        int i = ftdi->command_head;        while (I-- > 0) {                struct u132_command *command = &ftdi->command[COMMAND_MASK &                        i++];                total_size += 5 + command->follows;        } return total_size;}static int ftdi_elan_command_engine(struct usb_ftdi *ftdi){        int retval;        char *buf;        int ed_commands;        int total_size;        struct urb *urb;        int command_size = ftdi->command_next - ftdi->command_head;        if (command_size == 0)                return 0;        total_size = ftdi_elan_total_command_size(ftdi, command_size);        urb = usb_alloc_urb(0, GFP_KERNEL);        if (!urb) {                dev_err(&ftdi->udev->dev, "could not get a urb to write %d comm"                        "ands totaling %d bytes to the Uxxx\n", command_size,                        total_size);                return -ENOMEM;        }        buf = usb_buffer_alloc(ftdi->udev, total_size, GFP_KERNEL,                &urb->transfer_dma);        if (!buf) {                dev_err(&ftdi->udev->dev, "could not get a buffer to write %d c"                        "ommands totaling %d bytes to the Uxxx\n", command_size,                         total_size);                usb_free_urb(urb);                return -ENOMEM;        }        ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf,                command_size, total_size);        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,                ftdi->bulk_out_endpointAddr), buf, total_size,                ftdi_elan_write_bulk_callback, ftdi);        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;        if (ed_commands) {                char diag[40 *3 + 4];                char *d = diag;                int m = total_size;                u8 *c = buf;                int s = (sizeof(diag) - 1) / 3;                diag[0] = 0;                while (s-- > 0 && m-- > 0) {                        if (s > 0 || m == 0) {                                d += sprintf(d, " %02X", *c++);                        } else                                d += sprintf(d, " ..");                }        }        retval = usb_submit_urb(urb, GFP_KERNEL);        if (retval) {                dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write "                        "%d commands totaling %d bytes to the Uxxx\n", retval,                        urb, command_size, total_size);                usb_buffer_free(ftdi->udev, total_size, buf, urb->transfer_dma);                usb_free_urb(urb);                return retval;        }        usb_free_urb(urb);        /* release our reference to this urb,                the USB core will eventually free it entirely */        ftdi->command_head += command_size;        ftdi_elan_kick_respond_queue(ftdi);        return 0;}static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,        struct u132_target *target, u8 *buffer, int length){        struct urb *urb = target->urb;        int halted = target->halted;        int skipped = target->skipped;        int actual = target->actual;        int non_null = target->non_null;        int toggle_bits = target->toggle_bits;        int error_count = target->error_count;        int condition_code = target->condition_code;        int repeat_number = target->repeat_number;        void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int,                int, int, int, int) = target->callback;        target->active -= 1;        target->callback = NULL;        (*callback) (target->endp, urb, buffer, length, toggle_bits,                error_count, condition_code, repeat_number, halted, skipped,                actual, non_null);}static char *have_ed_set_response(struct usb_ftdi *ftdi,        struct u132_target *target, u16 ed_length, int ed_number, int ed_type,        char *b){        int payload = (ed_length >> 0) & 0x07FF;        mutex_lock(&ftdi->u132_lock);        target->actual = 0;        target->non_null = (ed_length >> 15) & 0x0001;        target->repeat_number = (ed_length >> 11) & 0x000F;        if (ed_type == 0x02) {                if (payload == 0 || target->abandoning > 0) {                        target->abandoning = 0;                        mutex_unlock(&ftdi->u132_lock);                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,                                payload);                        ftdi->recieved = 0;                        ftdi->expected = 4;                        ftdi->ed_found = 0;                        return ftdi->response;                } else {                        ftdi->expected = 4 + payload;                        ftdi->ed_found = 1;                        mutex_unlock(&ftdi->u132_lock);                        return b;                }        } else if (ed_type == 0x03) {                if (payload == 0 || target->abandoning > 0) {                        target->abandoning = 0;                        mutex_unlock(&ftdi->u132_lock);                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,                                payload);                        ftdi->recieved = 0;                        ftdi->expected = 4;                        ftdi->ed_found = 0;                        return ftdi->response;                } else {                        ftdi->expected = 4 + payload;                        ftdi->ed_found = 1;                        mutex_unlock(&ftdi->u132_lock);                        return b;                }        } else if (ed_type == 0x01) {                target->abandoning = 0;                mutex_unlock(&ftdi->u132_lock);                ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,                        payload);                ftdi->recieved = 0;                ftdi->expected = 4;                ftdi->ed_found = 0;                return ftdi->response;        } else {                target->abandoning = 0;                mutex_unlock(&ftdi->u132_lock);                ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,                        payload);                ftdi->recieved = 0;                ftdi->expected = 4;                ftdi->ed_found = 0;                return ftdi->response;        }}static char *have_ed_get_response(struct usb_ftdi *ftdi,        struct u132_target *target, u16 ed_length, int ed_number, int ed_type,        char *b){        mutex_lock(&ftdi->u132_lock);        target->condition_code = TD_DEVNOTRESP;        target->actual = (ed_length >> 0) & 0x01FF;        target->non_null = (ed_length >> 15) & 0x0001;        target->repeat_number = (ed_length >> 11) & 0x000F;        mutex_unlock(&ftdi->u132_lock);        if (target->active)                ftdi_elan_do_callback(ftdi, target, NULL, 0);        target->abandoning = 0;        ftdi->recieved = 0;        ftdi->expected = 4;        ftdi->ed_found = 0;        return ftdi->response;}/** The engine tries to empty the FTDI fifo** all responses found in the fifo data are dispatched thus* the response buffer can only ever hold a maximum sized* response from the Uxxx.**/static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi){        u8 *b = ftdi->response + ftdi->recieved;        int bytes_read = 0;        int retry_on_empty = 1;        int retry_on_timeout = 3;        int empty_packets = 0;      read:{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -