summaryrefslogtreecommitdiff
path: root/docs/en/demo/usbh_vendor.rst
blob: 09afe1cd3c2edade3512d1c812d75cca72600a10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
Writing Vendor Host Driver
============================================

This section mainly introduces how to write a vendor host driver.

- First copy a class/template/usbh_xxx.c file

- Define class driver and use CLASS_INFO_DEFINE prefix, so that after enumeration is completed, the protocol stack automatically finds the corresponding driver through usbd_class_find_driver.

.. code-block:: C

    static const struct usbh_class_driver xxx_class_driver = {
        .driver_name = "xxx",
        .connect = usbh_xxx_connect,
        .disconnect = usbh_xxx_disconnect
    };

    CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = {
        .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
        .bInterfaceClass = 0,
        .bInterfaceSubClass = 0,
        .bInterfaceProtocol = 0,
        .id_table = NULL,
        .class_driver = &xxx_class_driver
    };


- Implement connect and disconnect functions. In the connect function, you need to allocate an xxx_class structure. In the disconnect function, release the urb and xxx_class.

.. code-block:: C

    struct usbh_xxx {
        struct usbh_hubport *hport;
        struct usb_endpoint_descriptor *xxxin;
        struct usb_endpoint_descriptor *xxxout;
        struct usbh_urb xxxin_urb;
        struct usbh_urb xxxout_urb;

        uint8_t intf; /* interface number */
        uint8_t minor;

        void *user_data;
    };

    static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf)
    {
        struct usb_endpoint_descriptor *ep_desc;
        int ret;

        struct usbh_xxx *xxx_class = usbh_xxx_class_alloc();
        if (xxx_class == NULL) {
            USB_LOG_ERR("Fail to alloc xxx_class\r\n");
            return -USB_ERR_NOMEM;
        }

        return ret;
    }


    static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
    {
        int ret = 0;

        struct usbh_xxx *xxx_class = (struct usbh_xxx *)hport->config.intf[intf].priv;

        if (xxx_class) {
            if (xxx_class->xxxin) {
                usbh_kill_urb(&xxx_class->xxxin_urb);
            }

            if (xxx_class->xxxout) {
                usbh_kill_urb(&xxx_class->xxxout_urb);
            }

            if (hport->config.intf[intf].devname[0] != '\0') {
                USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
                usbh_xxx_stop(xxx_class);
            }

            usbh_xxx_class_free(xxx_class);
        }

        return ret;
    }

- Initialize endpoints

.. code-block:: C

        for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
        ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
        if (ep_desc->bEndpointAddress & 0x80) {
            USBH_EP_INIT(xxx_class->intin, ep_desc);
        } else {
            USBH_EP_INIT(xxx_class->intout, ep_desc);
        }
    }

- Finally design send/receive APIs, design them as synchronous or asynchronous according to actual conditions.

.. code-block:: C

    int usbh_xxx_in_transfer(struct usbh_xxx *xxx_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
    {
        int ret;
        struct usbh_urb *urb = &xxx_class->xxxin_urb;

        usbh_xxx_urb_fill(urb, xxx_class->hport, xxx_class->xxxin, buffer, buflen, timeout, NULL, NULL);
        ret = usbh_submit_urb(urb);
        if (ret == 0) {
            ret = urb->actual_length;
        }
        return ret;
    }

    int usbh_xxx_out_transfer(struct usbh_xxx *xxx_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
    {
        int ret;
        struct usbh_urb *urb = &xxx_class->xxxout_urb;

        usbh_xxx_urb_fill(urb, xxx_class->hport, xxx_class->xxxout, buffer, buflen, timeout, NULL, NULL);
        ret = usbh_submit_urb(urb);
        if (ret == 0) {
            ret = urb->actual_length;
        }
        return ret;
    }