|
| 1 | +/* |
| 2 | + * File : winusb.c |
| 3 | + * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team |
| 4 | + * |
| 5 | + * Change Logs: |
| 6 | + * Date Author Notes |
| 7 | + * 2017-11-16 ZYH first version |
| 8 | + */ |
| 9 | +#include <rthw.h> |
| 10 | +#include <rtthread.h> |
| 11 | +#include <rtservice.h> |
| 12 | +#include <rtdevice.h> |
| 13 | +#include <drivers/usb_device.h> |
| 14 | +#include "winusb.h" |
| 15 | +struct winusb_device |
| 16 | +{ |
| 17 | + uep_t ep_out; |
| 18 | + uep_t ep_in; |
| 19 | +}; |
| 20 | + |
| 21 | +typedef struct winusb_device * winusb_device_t; |
| 22 | + |
| 23 | +static struct udevice_descriptor dev_desc = |
| 24 | +{ |
| 25 | + USB_DESC_LENGTH_DEVICE, //bLength; |
| 26 | + USB_DESC_TYPE_DEVICE, //type; |
| 27 | + USB_BCD_VERSION, //bcdUSB; |
| 28 | + 0x00, //bDeviceClass; |
| 29 | + 0x00, //bDeviceSubClass; |
| 30 | + 0x00, //bDeviceProtocol; |
| 31 | + 0x40, //bMaxPacketSize0; |
| 32 | + _VENDOR_ID, //idVendor; |
| 33 | + _PRODUCT_ID, //idProduct; |
| 34 | + USB_BCD_DEVICE, //bcdDevice; |
| 35 | + USB_STRING_MANU_INDEX, //iManufacturer; |
| 36 | + USB_STRING_PRODUCT_INDEX, //iProduct; |
| 37 | + USB_STRING_SERIAL_INDEX, //iSerialNumber; |
| 38 | + USB_DYNAMIC, //bNumConfigurations; |
| 39 | +}; |
| 40 | +//FS and HS needed |
| 41 | +static struct usb_qualifier_descriptor dev_qualifier = |
| 42 | +{ |
| 43 | + sizeof(dev_qualifier), |
| 44 | + USB_DESC_TYPE_DEVICEQUALIFIER, |
| 45 | + 0x0200, |
| 46 | + 0x00, |
| 47 | + 0x00, |
| 48 | + 64, |
| 49 | + 0x01, |
| 50 | + 0, |
| 51 | +}; |
| 52 | + |
| 53 | +struct winusb_descriptor _winusb_desc = |
| 54 | +{ |
| 55 | +#ifdef RT_USB_DEVICE_COMPOSITE |
| 56 | + /* Interface Association Descriptor */ |
| 57 | + USB_DESC_LENGTH_IAD, |
| 58 | + USB_DESC_TYPE_IAD, |
| 59 | + USB_DYNAMIC, |
| 60 | + 0x01, |
| 61 | + 0xFF, |
| 62 | + 0x00, |
| 63 | + 0x00, |
| 64 | + 0x00, |
| 65 | +#endif |
| 66 | + /*interface descriptor*/ |
| 67 | + USB_DESC_LENGTH_INTERFACE, //bLength; |
| 68 | + USB_DESC_TYPE_INTERFACE, //type; |
| 69 | + USB_DYNAMIC, //bInterfaceNumber; |
| 70 | + 0x00, //bAlternateSetting; |
| 71 | + 0x02, //bNumEndpoints |
| 72 | + 0xFF, //bInterfaceClass; |
| 73 | + 0x00, //bInterfaceSubClass; |
| 74 | + 0x00, //bInterfaceProtocol; |
| 75 | + 0x00, //iInterface; |
| 76 | + /*endpoint descriptor*/ |
| 77 | + USB_DESC_LENGTH_ENDPOINT, |
| 78 | + USB_DESC_TYPE_ENDPOINT, |
| 79 | + USB_DYNAMIC | USB_DIR_OUT, |
| 80 | + USB_EP_ATTR_BULK, |
| 81 | + 0x40, |
| 82 | + 0x00, |
| 83 | + /*endpoint descriptor*/ |
| 84 | + USB_DESC_LENGTH_ENDPOINT, |
| 85 | + USB_DESC_TYPE_ENDPOINT, |
| 86 | + USB_DYNAMIC | USB_DIR_IN, |
| 87 | + USB_EP_ATTR_BULK, |
| 88 | + 0x40, |
| 89 | + 0x00, |
| 90 | +}; |
| 91 | + |
| 92 | + |
| 93 | +const static char* _ustring[] = |
| 94 | +{ |
| 95 | + "Language", |
| 96 | + "RT-Thread Team.", |
| 97 | + "RTT Win USB", |
| 98 | + "32021919830108", |
| 99 | + "Configuration", |
| 100 | + "Interface", |
| 101 | + USB_STRING_OS//must be |
| 102 | +}; |
| 103 | +struct usb_os_function_comp_id_descriptor winusb_func_comp_id_desc = |
| 104 | +{ |
| 105 | + .bFirstInterfaceNumber = USB_DYNAMIC, |
| 106 | + .reserved1 = 0x01, |
| 107 | + .compatibleID = {'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00}, |
| 108 | + .subCompatibleID = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
| 109 | + .reserved2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} |
| 110 | +}; |
| 111 | + |
| 112 | +static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size) |
| 113 | +{ |
| 114 | + struct winusb_device* data = (struct winusb_device*)func->user_data; |
| 115 | + rt_kprintf("recev:%s",data->ep_out->buffer); |
| 116 | + data->ep_in->request.buffer = data->ep_out->buffer; |
| 117 | + data->ep_in->request.size = EP_MAXPACKET(data->ep_out); |
| 118 | + |
| 119 | + data->ep_in->request.req_type = UIO_REQUEST_WRITE; |
| 120 | + rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request); |
| 121 | + return RT_EOK; |
| 122 | +} |
| 123 | + |
| 124 | +static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size) |
| 125 | +{ |
| 126 | + return RT_EOK; |
| 127 | +} |
| 128 | +static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) |
| 129 | +{ |
| 130 | + return RT_EOK; |
| 131 | +} |
| 132 | +static rt_err_t _function_enable(ufunction_t func) |
| 133 | +{ |
| 134 | + RT_ASSERT(func != RT_NULL); |
| 135 | + struct winusb_device* data = (struct winusb_device*)func->user_data; |
| 136 | + data->ep_out->buffer = rt_malloc(0x40); |
| 137 | + |
| 138 | + data->ep_out->request.buffer = data->ep_out->buffer; |
| 139 | + data->ep_out->request.size = EP_MAXPACKET(data->ep_out); |
| 140 | + |
| 141 | + data->ep_out->request.req_type = UIO_REQUEST_READ_BEST; |
| 142 | + rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request); |
| 143 | + return RT_EOK; |
| 144 | +} |
| 145 | +static rt_err_t _function_disable(ufunction_t func) |
| 146 | +{ |
| 147 | + RT_ASSERT(func != RT_NULL); |
| 148 | + struct winusb_device* data = (struct winusb_device*)func->user_data; |
| 149 | + if(data->ep_out->buffer != RT_NULL) |
| 150 | + { |
| 151 | + rt_free(data->ep_out->buffer); |
| 152 | + data->ep_out->buffer = RT_NULL; |
| 153 | + } |
| 154 | + return RT_EOK; |
| 155 | +} |
| 156 | + |
| 157 | +static struct ufunction_ops ops = |
| 158 | +{ |
| 159 | + _function_enable, |
| 160 | + _function_disable, |
| 161 | + RT_NULL, |
| 162 | +}; |
| 163 | + |
| 164 | +static rt_err_t _winusb_descriptor_config(winusb_desc_t winusb, rt_uint8_t cintf_nr) |
| 165 | +{ |
| 166 | +#ifdef RT_USB_DEVICE_COMPOSITE |
| 167 | + winusb->iad_desc.bFirstInterface = cintf_nr; |
| 168 | +#endif |
| 169 | + winusb_func_comp_id_desc.bFirstInterfaceNumber = cintf_nr; |
| 170 | + return RT_EOK; |
| 171 | +} |
| 172 | +static rt_err_t rt_usb_winusb_init(ufunction_t func) |
| 173 | +{ |
| 174 | + return RT_EOK; |
| 175 | +} |
| 176 | + |
| 177 | +ufunction_t rt_usbd_function_winusb_create(udevice_t device) |
| 178 | +{ |
| 179 | + ufunction_t func; |
| 180 | + winusb_device_t winusb_device; |
| 181 | + |
| 182 | + uintf_t winusb_intf; |
| 183 | + ualtsetting_t winusb_setting; |
| 184 | + winusb_desc_t winusb_desc; |
| 185 | + |
| 186 | + /* parameter check */ |
| 187 | + RT_ASSERT(device != RT_NULL); |
| 188 | + |
| 189 | + /* set usb device string description */ |
| 190 | + rt_usbd_device_set_string(device, _ustring); |
| 191 | + |
| 192 | + /* create a cdc function */ |
| 193 | + func = rt_usbd_function_new(device, &dev_desc, &ops); |
| 194 | + rt_usbd_device_set_qualifier(device, &dev_qualifier); |
| 195 | + |
| 196 | + /* allocate memory for cdc vcom data */ |
| 197 | + winusb_device = (winusb_device_t)rt_malloc(sizeof(struct winusb_device)); |
| 198 | + rt_memset((void *)winusb_device, 0, sizeof(struct winusb_device)); |
| 199 | + func->user_data = (void*)winusb_device; |
| 200 | + |
| 201 | + /* create an interface object */ |
| 202 | + winusb_intf = rt_usbd_interface_new(device, _interface_handler); |
| 203 | + |
| 204 | + /* create an alternate setting object */ |
| 205 | + winusb_setting = rt_usbd_altsetting_new(sizeof(struct winusb_descriptor)); |
| 206 | + |
| 207 | + /* config desc in alternate setting */ |
| 208 | + rt_usbd_altsetting_config_descriptor(winusb_setting, &_winusb_desc, (rt_off_t)&((winusb_desc_t)0)->intf_desc); |
| 209 | + |
| 210 | + /* configure the hid interface descriptor */ |
| 211 | + _winusb_descriptor_config(winusb_setting->desc, winusb_intf->intf_num); |
| 212 | + |
| 213 | + /* create endpoint */ |
| 214 | + winusb_desc = (winusb_desc_t)winusb_setting->desc; |
| 215 | + winusb_device->ep_out = rt_usbd_endpoint_new(&winusb_desc->ep_out_desc, _ep_out_handler); |
| 216 | + winusb_device->ep_in = rt_usbd_endpoint_new(&winusb_desc->ep_in_desc, _ep_in_handler); |
| 217 | + |
| 218 | + /* add the int out and int in endpoint to the alternate setting */ |
| 219 | + rt_usbd_altsetting_add_endpoint(winusb_setting, winusb_device->ep_out); |
| 220 | + rt_usbd_altsetting_add_endpoint(winusb_setting, winusb_device->ep_in); |
| 221 | + |
| 222 | + /* add the alternate setting to the interface, then set default setting */ |
| 223 | + rt_usbd_interface_add_altsetting(winusb_intf, winusb_setting); |
| 224 | + rt_usbd_set_altsetting(winusb_intf, 0); |
| 225 | + |
| 226 | + /* add the interface to the mass storage function */ |
| 227 | + rt_usbd_function_add_interface(func, winusb_intf); |
| 228 | + |
| 229 | + rt_usbd_os_comp_id_desc_add_os_func_comp_id_desc(device->os_comp_id_desc, &winusb_func_comp_id_desc); |
| 230 | + /* initilize hid */ |
| 231 | + rt_usb_winusb_init(func); |
| 232 | + return func; |
| 233 | +} |
| 234 | + |
0 commit comments