реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Драйверы USB TMC для linux
_galb_
сообщение Oct 3 2012, 09:52
Сообщение #1





Группа: Участник
Сообщений: 12
Регистрация: 22-08-12
Пользователь №: 73 215



Доброго дня всем!
Нужно создать драйвер устройства USB TMC (Test and Measurement Class) Gadget, ОС linux (дистрибутив linux-davinci), процессор AM1808 от TI.
Есть ли здесь у кого опыт создания устройств usb gadget для linux? Есть вопросы...

Go to the top of the page
 
+Quote Post
gosha
сообщение Oct 9 2012, 06:40
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 216
Регистрация: 15-06-04
Из: Менделеево
Пользователь №: 30



QUOTE (_galb_ @ Oct 3 2012, 13:52) *
Доброго дня всем!
Нужно создать драйвер устройства USB TMC (Test and Measurement Class) Gadget, ОС linux (дистрибутив linux-davinci), процессор AM1808 от TI.
Есть ли здесь у кого опыт создания устройств usb gadget для linux? Есть вопросы...

Есть опыт написания драйверов usb-storage, usb-video.
Там все по аналогии с имеющимся драйвером похожего устройства. делается
Go to the top of the page
 
+Quote Post
_galb_
сообщение Oct 10 2012, 05:58
Сообщение #3





Группа: Участник
Сообщений: 12
Регистрация: 22-08-12
Пользователь №: 73 215



Цитата(gosha @ Oct 9 2012, 12:40) *
Есть опыт написания драйверов usb-storage, usb-video.

Со стороны хоста, или со стороны гаджета?

Мои вопросы состоят примерно в следующем:
1) В папке drivers/usb/gadget во всех драйверах используются функции библиотеки composite.c. Например, драйвер регистрируется с помощью функции usb_composite_probe, которая в свою очередь вызывает usb_gadget_probe_driver, описанную в include/linux/usb/gadget.h. А реализация этой функции, похоже, у каждого драйвера своя. Например, для драйвера zero.c её нет в явном виде, и мне не понятно, в каком направлении дальше идёт регистрация драйвера Gadget Zero в системе...
2) Если продолжить рассматривать драйвер zero.c, то там явно описывается только дескриптор устройства ( в структуре zero_driver = { <...>, .dev = &device_desc, <...> } ). Остальные дескрипторы (Configuration Descriptor, Interface Descriptor), похоже, инициализируются где-то через функции composite.c. Мне не понятно, как их (дескрипторы) задавать (например, для USB TMC устройств мне нужно прописать bInterfaceClass = 0xFE, bInterfaceSubClass = 3, bInterfaceProtocol = 1).
Go to the top of the page
 
+Quote Post
gosha
сообщение Oct 10 2012, 10:27
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 216
Регистрация: 15-06-04
Из: Менделеево
Пользователь №: 30



QUOTE (_galb_ @ Oct 10 2012, 09:58) *
Со стороны хоста, или со стороны гаджета?

Мои вопросы состоят примерно в следующем:
1) В папке drivers/usb/gadget во всех драйверах используются функции библиотеки composite.c. Например, драйвер регистрируется с помощью функции usb_composite_probe, которая в свою очередь вызывает usb_gadget_probe_driver, описанную в include/linux/usb/gadget.h. А реализация этой функции, похоже, у каждого драйвера своя. Например, для драйвера zero.c её нет в явном виде, и мне не понятно, в каком направлении дальше идёт регистрация драйвера Gadget Zero в системе...
2) Если продолжить рассматривать драйвер zero.c, то там явно описывается только дескриптор устройства ( в структуре zero_driver = { <...>, .dev = &device_desc, <...> } ). Остальные дескрипторы (Configuration Descriptor, Interface Descriptor), похоже, инициализируются где-то через функции composite.c. Мне не понятно, как их (дескрипторы) задавать (например, для USB TMC устройств мне нужно прописать bInterfaceClass = 0xFE, bInterfaceSubClass = 3, bInterfaceProtocol = 1).


Со стороны хоста.

Какая версия ядра?

Драйвер при загрузке insmod в сообщает таблицу usb дескрипторов, при подключении каких usb idVendor idProduct и пр необходимо запустить его ф-ю по-пробовать и поднять драйвер.
При подсоединении устройства, usb_core определяет его bDeviceClass idVendor idProduct , какой драйвер зарегистрировался на это устройство.
Дальше пусть этот драйвер сам разбирается с этим устройством.
usb_core запускает ф-ю probe() драйвера, который зарегистрировался на этот тип usb устройств.
Эта ф-я проверяет устройство и поднимает его интерфейсы.
Напр, если это eth драйвер, в системе регистрируется напр eth2.
В данном случае, это ф-я bind()

При извлечении usb устройства, интерфейс unregister: eth_unbind().


CODE
static struct usb_device_descriptor     [u]device_desc[/u] = {
    .bDescriptorType =    USB_DT_DEVICE,
    .bcdUSB =        cpu_to_le16 (0x0200),
    .bDeviceClass =        USB_CLASS_COMM,
    .bDeviceSubClass =    0,
    .bDeviceProtocol =    0,
    .idVendor =        cpu_to_le16 (CDC_VENDOR_NUM),
    .idProduct =        cpu_to_le16 (CDC_PRODUCT_NUM),
}

static int __ref eth_bind(struct usb_composite_dev *cdev)
{...}
static struct usb_composite_driver eth_driver = {
    .[b]dev[/b]        = &[u]device_desc[/u],
    .strings    = dev_strings,
    .[b]bind[/b]        = [b]eth_bind[/b],
    .[b]unbind[/b]        = __exit_p([b]eth_unbind[/b]),
};


http://lwn.net/Articles/395712/
Go to the top of the page
 
+Quote Post
_galb_
сообщение Oct 17 2012, 10:11
Сообщение #5





Группа: Участник
Сообщений: 12
Регистрация: 22-08-12
Пользователь №: 73 215



Цитата(gosha @ Oct 10 2012, 16:27) *
Какая версия ядра?

Linux-2.6.37, сборка linux-davinci

Цитата(gosha @ Oct 10 2012, 16:27) *
При подсоединении устройства, usb_core определяет его bDeviceClass idVendor idProduct , какой драйвер зарегистрировался на это устройство.
Дальше пусть этот драйвер сам разбирается с этим устройством.

Как раз и интересно, как дальше драйвер разбирается с устройством. Как я вижу, стандартные запросы USB (GET_STATUS, CLEAR_FEATURE, ...) обрабатываются в функции composite_setup (библиотеки composite.c). Пока не понятно, где обрабатываются специфические для класса запросы (например, для TMC запрос GET_CAPABILITY). Ну и мехинизм посылки ответа хосту тоже не до конца понятен...

Может, конечно, я туплю, но пока что из всего, что прочитано, как надо сделать до меня не дошло laughing.gif

Сообщение отредактировал _galb_ - Oct 17 2012, 10:12
Go to the top of the page
 
+Quote Post
gosha
сообщение Oct 18 2012, 14:32
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 216
Регистрация: 15-06-04
Из: Менделеево
Пользователь №: 30



QUOTE (_galb_ @ Oct 17 2012, 14:11) *
Linux-2.6.37, сборка linux-davinci


Как раз и интересно, как дальше драйвер разбирается с устройством. Как я вижу, стандартные запросы USB (GET_STATUS, CLEAR_FEATURE, ...) обрабатываются в функции composite_setup (библиотеки composite.c). Пока не понятно, где обрабатываются специфические для класса запросы (например, для TMC запрос GET_CAPABILITY). Ну и мехинизм посылки ответа хосту тоже не до конца понятен...

Может, конечно, я туплю, но пока что из всего, что прочитано, как надо сделать до меня не дошло laughing.gif


Не понятно что?: как устройство зарегистрировать в ситеме при его подключении и записать в регистры usb устройства его настройки?
Или как написать интерфейсные ф-ии драйвераа, к которым будет обращаться приложение?

Если необходимо писать в регистры устройства (например, я задавал частоту и разрешение кадров видеокамеры)

QUOTE
3. Для инициализации камеры послать управляющие посылки (Vendor Request)

(IN UCHAR Request, IN USHORT Value, IN USHORT Index)

0x0A, 0x01, 0x0F
0x0A, 0x03, 0x0F
0x0A, 0x01, 0x0F
0x0A, 0x00, 0x60
0x0A, 0x01, 0x02
Задержка в 2 мс.
0x0A, 0x15, 0x0F

4. Включить камеру на передачу кадров по Pipe: 1 Type: BLK
0x0A, 0x1F,0x0F;

5. Принимать кадры по Pipe: 1 (Bulk Read) (MaxPktSize: 0x200)

6. Выключить камеру после окончания приема.
0x0A, 0x1D, 0x0F


CODE
static int vec135_cmd_tx(struct usb_vec135 *vec135, unsigned short req, unsigned short value, unsigned short index)
{int ret = usb_control_msg (vec135->udev, usb_sndctrlpipe(vec135->udev, 0), req,
        USB_DIR_OUT | USB_TYPE_VENDOR, value, index, NULL, 0, 5000);
if (ret < 0)
    printk("%s> error: returned %d for 0x%x 0x%x 0x%x\n", __FUNCTION__, ret, req, value, index);
else
    printk("%s> req 0x%02x 0x%02x 0x%02x\n", __FUNCTION__, req, value, index);
return ret;
}



static int vec135_init(struct usb_vec135 *vec135) {
    vec135_cmd_tx( vec135, 0x0A, 0x01,0x0F);
    vec135_cmd_tx( vec135, 0x0A, 0x03,0x0F);
    vec135_cmd_tx( vec135, 0x0A, 0x01,0x0F);
    vec135_cmd_tx( vec135, 0x0A, 0x60,0x00);
    vec135_cmd_tx( vec135, 0x0A, 0x00,0x60);
    vec135_cmd_tx( vec135, 0x0A, 0x01,0x02);
    msleep(200);
    vec135_cmd_tx( vec135, 0x0A, 0x15, 0x0F);
    return 0;
}
Go to the top of the page
 
+Quote Post
_galb_
сообщение Oct 23 2012, 04:22
Сообщение #7





Группа: Участник
Сообщений: 12
Регистрация: 22-08-12
Пользователь №: 73 215



gosha, спасибо Вам за ответ, стало более понятно sm.gif

Цитата(gosha @ Oct 18 2012, 20:32) *
Не понятно что?: как устройство зарегистрировать в ситеме при его подключении и записать в регистры usb устройства его настройки?
Или как написать интерфейсные ф-ии драйвераа, к которым будет обращаться приложение?

а вообще да, интересует как написать интерфейсные ф-ии драйвера, к которым будет обращаться приложение.


Сообщение отредактировал _galb_ - Oct 23 2012, 04:15
Go to the top of the page
 
+Quote Post
_galb_
сообщение Oct 24 2012, 05:07
Сообщение #8





Группа: Участник
Сообщений: 12
Регистрация: 22-08-12
Пользователь №: 73 215



gosha, ещё вопрос... в своём драйвере Вы использовали потоки (thread), или можно без них обойтись?
Go to the top of the page
 
+Quote Post
gosha
сообщение Oct 24 2012, 07:18
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 216
Регистрация: 15-06-04
Из: Менделеево
Пользователь №: 30



QUOTE (_galb_ @ Oct 24 2012, 09:07) *
gosha, ещё вопрос... в своём драйвере Вы использовали потоки (thread), или можно без них обойтись?


При написании драйверов не используются thread.
При написании драйверов USB используются только call-back ф-ии, которые вызывает usb-core, когда устройство прислало ответ на команду.

я использовал ф-ии usb_submit_urb(urb) для обмена данными с устройством.
Например:
CODE
/*============================================================================*/
static void uvc_video_complete(struct urb *urb)
{struct uvc_video_device *video = urb->context;
struct uvc_video_queue *queue = &video->queue;

int ret;
if (video->removed)
    return;
switch (urb->status)
    {case 0:
        break;
     default:
        uvc_printk(KERN_WARNING, "Non-zero status (%d) in video completion handler.\n", urb->status);
     case -ENOENT:        /* usb_unlink_urb() called. */
        if (video->frozen)
            return;
     case -ECONNRESET:    /* usb_unlink_urb() called. */
     case -ESHUTDOWN:    /* The endpoint is being disabled. */
        uvc_queue_enable(queue, 0);
        return;
    }
if(queue->flags & UVC_QUEUE_STREAMING)
    {struct uvc_buffer *buf = NULL;
     unsigned long flags;
     spin_lock_irqsave(&queue->irqlock, flags);
     buf= &queue->buffer[queue->buf_tail];
     spin_unlock_irqrestore(&queue->irqlock, flags);
     video->decode(urb, video, buf);
     urb->dev = video->uvc_dev->udev;
     urb->status = 0;
    if ((ret = usb_submit_urb(urb)) < 0)
        {uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", ret);}
    }
return;
}

/*=================================================*/
urb = usb_alloc_urb(npackets<<4);
urb->dev = video->uvc_dev->udev;
urb->context = video;
urb->pipe = usb_rcvisocpipe(video->uvc_dev->udev, ep->bEndpointAddress);
urb->transfer_flags = USB_ISO_ASAP;
urb->interval = 1;//ep->bInterval;
urb->transfer_buffer = video->urb_buffer[i];
urb->complete = uvc_video_complete; /* эта функция будет вызвана, когда вернется ответ (данные от устройства) */
urb->number_of_packets = npackets;
urb->transfer_buffer_length = size;
if ((ret = usb_submit_urb(urb)) < 0)
        {uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", ret);}




Прикладная программа обращается к драйверу через системные вызовы
open()
close()
read()
write()
ioctl()
poll()

Соответственно, необходимо в драйвере написать эти ф-ии, которые будут вызываться ядром ОС Linux при обращении к устройству прикладной программы. И зарегистрировать их в системе.

Для драйвера usb видеокамеры у меня:
CODE
struct file_operations uvc_fops = {
    .owner        = THIS_MODULE,
    .open        = uvc_v4l2_open,
    .release    = uvc_v4l2_release,
    .ioctl        = uvc_v4l2_ioctl,
    .llseek        = no_llseek,
    .read        = uvc_v4l2_read,
    .mmap        = uvc_v4l2_mmap,
    .poll        = uvc_v4l2_poll,
}
video_register_device (uvc_fops)

Go to the top of the page
 
+Quote Post
_galb_
сообщение Oct 26 2012, 04:58
Сообщение #10





Группа: Участник
Сообщений: 12
Регистрация: 22-08-12
Пользователь №: 73 215



Цитата(gosha @ Oct 24 2012, 13:18) *
При написании драйверов не используются thread.

и всё же, в драйвере устройства mass_storage (linux-davinci/drivers/usb/gadget/mass_storage.c) создаётся thread (в функции fsg_common_init вызывается kthread_create).
Go to the top of the page
 
+Quote Post
gosha
сообщение Nov 8 2012, 10:16
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 216
Регистрация: 15-06-04
Из: Менделеево
Пользователь №: 30



QUOTE (_galb_ @ Oct 26 2012, 08:58) *
и всё же, в драйвере устройства mass_storage (linux-davinci/drivers/usb/gadget/mass_storage.c) создаётся thread (в функции fsg_common_init вызывается kthread_create).


Понял. Возможен и такой вариант.
Go to the top of the page
 
+Quote Post
_galb_
сообщение Nov 9 2012, 07:44
Сообщение #12





Группа: Участник
Сообщений: 12
Регистрация: 22-08-12
Пользователь №: 73 215



хорошо, с регистрацией и определением устройства в системе понятно, работает.
теперь... вот хост отправил данные устройству в конечную точку (типа bulk) с помощью функции usb_bulk_msg. как мне в устройстве принять данные в конечную точку?
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 19:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01463 секунд с 7
ELECTRONIX ©2004-2016