1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2017-11-16 ZYH first version 9 */ 10 #include <rthw.h> 11 #include <rtthread.h> 12 #include <rtservice.h> 13 #include <rtdevice.h> 14 #include <drivers/usb_device.h> 15 #include "winusb.h" 16 struct winusb_device 17 { 18 struct rt_device parent; 19 void (*cmd_handler)(rt_uint8_t *buffer,rt_size_t size); 20 rt_uint8_t cmd_buff[256]; 21 uep_t ep_out; 22 uep_t ep_in; 23 }; 24 25 typedef struct winusb_device * winusb_device_t; 26 27 ALIGN(4) 28 static struct udevice_descriptor dev_desc = 29 { 30 USB_DESC_LENGTH_DEVICE, //bLength; 31 USB_DESC_TYPE_DEVICE, //type; 32 USB_BCD_VERSION, //bcdUSB; 33 0x00, //bDeviceClass; 34 0x00, //bDeviceSubClass; 35 0x00, //bDeviceProtocol; 36 0x40, //bMaxPacketSize0; 37 _VENDOR_ID, //idVendor; 38 _PRODUCT_ID, //idProduct; 39 USB_BCD_DEVICE, //bcdDevice; 40 USB_STRING_MANU_INDEX, //iManufacturer; 41 USB_STRING_PRODUCT_INDEX, //iProduct; 42 USB_STRING_SERIAL_INDEX, //iSerialNumber; 43 USB_DYNAMIC, //bNumConfigurations; 44 }; 45 46 //FS and HS needed 47 ALIGN(4) 48 static struct usb_qualifier_descriptor dev_qualifier = 49 { 50 sizeof(dev_qualifier), //bLength 51 USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType 52 0x0200, //bcdUSB 53 0xFF, //bDeviceClass 54 0x00, //bDeviceSubClass 55 0x00, //bDeviceProtocol 56 64, //bMaxPacketSize0 57 0x01, //bNumConfigurations 58 0, 59 }; 60 61 ALIGN(4) 62 struct winusb_descriptor _winusb_desc = 63 { 64 #ifdef RT_USB_DEVICE_COMPOSITE 65 /* Interface Association Descriptor */ 66 { 67 USB_DESC_LENGTH_IAD, 68 USB_DESC_TYPE_IAD, 69 USB_DYNAMIC, 70 0x01, 71 0xFF, 72 0x00, 73 0x00, 74 0x00, 75 }, 76 #endif 77 /*interface descriptor*/ 78 { 79 USB_DESC_LENGTH_INTERFACE, //bLength; 80 USB_DESC_TYPE_INTERFACE, //type; 81 USB_DYNAMIC, //bInterfaceNumber; 82 0x00, //bAlternateSetting; 83 0x02, //bNumEndpoints 84 0xFF, //bInterfaceClass; 85 0x00, //bInterfaceSubClass; 86 0x00, //bInterfaceProtocol; 87 0x00, //iInterface; 88 }, 89 /*endpoint descriptor*/ 90 { 91 USB_DESC_LENGTH_ENDPOINT, 92 USB_DESC_TYPE_ENDPOINT, 93 USB_DYNAMIC | USB_DIR_OUT, 94 USB_EP_ATTR_BULK, 95 USB_DYNAMIC, 96 0x00, 97 }, 98 /*endpoint descriptor*/ 99 { 100 USB_DESC_LENGTH_ENDPOINT, 101 USB_DESC_TYPE_ENDPOINT, 102 USB_DYNAMIC | USB_DIR_IN, 103 USB_EP_ATTR_BULK, 104 USB_DYNAMIC, 105 0x00, 106 }, 107 }; 108 109 ALIGN(4) 110 const static char* _ustring[] = 111 { 112 "Language", 113 "RT-Thread Team.", 114 "RTT Win USB", 115 "32021919830108", 116 "Configuration", 117 "Interface", 118 USB_STRING_OS//must be 119 }; 120 121 ALIGN(4) 122 struct usb_os_proerty winusb_proerty[] = 123 { 124 USB_OS_PROERTY_DESC(USB_OS_PROERTY_TYPE_REG_SZ,"DeviceInterfaceGUID",RT_WINUSB_GUID), 125 }; 126 127 ALIGN(4) 128 struct usb_os_function_comp_id_descriptor winusb_func_comp_id_desc = 129 { 130 .bFirstInterfaceNumber = USB_DYNAMIC, 131 .reserved1 = 0x01, 132 .compatibleID = {'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00}, 133 .subCompatibleID = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 134 .reserved2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 135 }; 136 137 static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size) 138 { 139 winusb_device_t winusb_device = (winusb_device_t)func->user_data; 140 if(winusb_device->parent.rx_indicate != RT_NULL) 141 { 142 winusb_device->parent.rx_indicate(&winusb_device->parent, size); 143 } 144 return RT_EOK; 145 } 146 147 static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size) 148 { 149 winusb_device_t winusb_device = (winusb_device_t)func->user_data; 150 if(winusb_device->parent.tx_complete != RT_NULL) 151 { 152 winusb_device->parent.tx_complete(&winusb_device->parent, winusb_device->ep_in->buffer); 153 } 154 return RT_EOK; 155 } 156 static ufunction_t cmd_func = RT_NULL; 157 static rt_err_t _ep0_cmd_handler(udevice_t device, rt_size_t size) 158 { 159 winusb_device_t winusb_device; 160 161 if(cmd_func != RT_NULL) 162 { 163 winusb_device = (winusb_device_t)cmd_func->user_data; 164 cmd_func = RT_NULL; 165 if(winusb_device->cmd_handler != RT_NULL) 166 { 167 winusb_device->cmd_handler(winusb_device->cmd_buff,size); 168 } 169 } 170 dcd_ep0_send_status(device->dcd); 171 return RT_EOK; 172 } 173 static rt_err_t _ep0_cmd_read(ufunction_t func, ureq_t setup) 174 { 175 winusb_device_t winusb_device = (winusb_device_t)func->user_data; 176 cmd_func = func; 177 rt_usbd_ep0_read(func->device,winusb_device->cmd_buff,setup->wLength,_ep0_cmd_handler); 178 return RT_EOK; 179 } 180 static rt_err_t _interface_handler(ufunction_t func, ureq_t setup) 181 { 182 switch(setup->bRequest) 183 { 184 case 'A': 185 switch(setup->wIndex) 186 { 187 case 0x05: 188 usbd_os_proerty_descriptor_send(func,setup,winusb_proerty,sizeof(winusb_proerty)/sizeof(winusb_proerty[0])); 189 break; 190 } 191 break; 192 case 0x0A://customer 193 _ep0_cmd_read(func, setup); 194 break; 195 } 196 197 return RT_EOK; 198 } 199 static rt_err_t _function_enable(ufunction_t func) 200 { 201 RT_ASSERT(func != RT_NULL); 202 return RT_EOK; 203 } 204 static rt_err_t _function_disable(ufunction_t func) 205 { 206 RT_ASSERT(func != RT_NULL); 207 return RT_EOK; 208 } 209 210 static struct ufunction_ops ops = 211 { 212 _function_enable, 213 _function_disable, 214 RT_NULL, 215 }; 216 217 static rt_err_t _winusb_descriptor_config(winusb_desc_t winusb, rt_uint8_t cintf_nr, rt_uint8_t device_is_hs) 218 { 219 #ifdef RT_USB_DEVICE_COMPOSITE 220 winusb->iad_desc.bFirstInterface = cintf_nr; 221 #endif 222 winusb->ep_out_desc.wMaxPacketSize = device_is_hs ? 512 : 64; 223 winusb->ep_in_desc.wMaxPacketSize = device_is_hs ? 512 : 64; 224 winusb_func_comp_id_desc.bFirstInterfaceNumber = cintf_nr; 225 return RT_EOK; 226 } 227 228 static rt_size_t win_usb_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) 229 { 230 if(((ufunction_t)dev->user_data)->device->state != USB_STATE_CONFIGURED) 231 { 232 return 0; 233 } 234 winusb_device_t winusb_device = (winusb_device_t)dev; 235 winusb_device->ep_out->buffer = buffer; 236 winusb_device->ep_out->request.buffer = buffer; 237 winusb_device->ep_out->request.size = size; 238 winusb_device->ep_out->request.req_type = UIO_REQUEST_READ_FULL; 239 rt_usbd_io_request(((ufunction_t)dev->user_data)->device,winusb_device->ep_out,&winusb_device->ep_out->request); 240 return size; 241 } 242 static rt_size_t win_usb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) 243 { 244 if(((ufunction_t)dev->user_data)->device->state != USB_STATE_CONFIGURED) 245 { 246 return 0; 247 } 248 winusb_device_t winusb_device = (winusb_device_t)dev; 249 winusb_device->ep_in->buffer = (void *)buffer; 250 winusb_device->ep_in->request.buffer = winusb_device->ep_in->buffer; 251 winusb_device->ep_in->request.size = size; 252 winusb_device->ep_in->request.req_type = UIO_REQUEST_WRITE; 253 rt_usbd_io_request(((ufunction_t)dev->user_data)->device,winusb_device->ep_in,&winusb_device->ep_in->request); 254 return size; 255 } 256 static rt_err_t win_usb_control(rt_device_t dev, int cmd, void *args) 257 { 258 winusb_device_t winusb_device = (winusb_device_t)dev; 259 if(RT_DEVICE_CTRL_CONFIG == cmd) 260 { 261 winusb_device->cmd_handler = (void(*)(rt_uint8_t*,rt_size_t))args; 262 } 263 return RT_EOK; 264 } 265 266 #ifdef RT_USING_DEVICE_OPS 267 const static struct rt_device_ops winusb_device_ops = 268 { 269 RT_NULL, 270 RT_NULL, 271 RT_NULL, 272 win_usb_read, 273 win_usb_write, 274 win_usb_control, 275 }; 276 #endif 277 278 static rt_err_t rt_usb_winusb_init(ufunction_t func) 279 { 280 winusb_device_t winusb_device = (winusb_device_t)func->user_data; 281 winusb_device->parent.type = RT_Device_Class_Miscellaneous; 282 283 #ifdef RT_USING_DEVICE_OPS 284 winusb_device->parent.ops = &winusb_device_ops; 285 #else 286 winusb_device->parent.init = RT_NULL; 287 winusb_device->parent.open = RT_NULL; 288 winusb_device->parent.close = RT_NULL; 289 winusb_device->parent.read = win_usb_read; 290 winusb_device->parent.write = win_usb_write; 291 winusb_device->parent.control = win_usb_control; 292 #endif 293 294 winusb_device->parent.user_data = func; 295 296 297 return rt_device_register(&winusb_device->parent, "winusb", RT_DEVICE_FLAG_RDWR); 298 } 299 300 ufunction_t rt_usbd_function_winusb_create(udevice_t device) 301 { 302 ufunction_t func; 303 winusb_device_t winusb_device; 304 305 uintf_t winusb_intf; 306 ualtsetting_t winusb_setting; 307 winusb_desc_t winusb_desc; 308 309 /* parameter check */ 310 RT_ASSERT(device != RT_NULL); 311 312 /* set usb device string description */ 313 rt_usbd_device_set_string(device, _ustring); 314 315 /* create a cdc function */ 316 func = rt_usbd_function_new(device, &dev_desc, &ops); 317 rt_usbd_device_set_qualifier(device, &dev_qualifier); 318 319 /* allocate memory for cdc vcom data */ 320 winusb_device = (winusb_device_t)rt_malloc(sizeof(struct winusb_device)); 321 rt_memset((void *)winusb_device, 0, sizeof(struct winusb_device)); 322 func->user_data = (void*)winusb_device; 323 /* create an interface object */ 324 winusb_intf = rt_usbd_interface_new(device, _interface_handler); 325 326 /* create an alternate setting object */ 327 winusb_setting = rt_usbd_altsetting_new(sizeof(struct winusb_descriptor)); 328 329 /* config desc in alternate setting */ 330 rt_usbd_altsetting_config_descriptor(winusb_setting, &_winusb_desc, (rt_off_t)&((winusb_desc_t)0)->intf_desc); 331 332 /* configure the hid interface descriptor */ 333 _winusb_descriptor_config(winusb_setting->desc, winusb_intf->intf_num, device->dcd->device_is_hs); 334 335 /* create endpoint */ 336 winusb_desc = (winusb_desc_t)winusb_setting->desc; 337 winusb_device->ep_out = rt_usbd_endpoint_new(&winusb_desc->ep_out_desc, _ep_out_handler); 338 winusb_device->ep_in = rt_usbd_endpoint_new(&winusb_desc->ep_in_desc, _ep_in_handler); 339 340 /* add the int out and int in endpoint to the alternate setting */ 341 rt_usbd_altsetting_add_endpoint(winusb_setting, winusb_device->ep_out); 342 rt_usbd_altsetting_add_endpoint(winusb_setting, winusb_device->ep_in); 343 344 /* add the alternate setting to the interface, then set default setting */ 345 rt_usbd_interface_add_altsetting(winusb_intf, winusb_setting); 346 rt_usbd_set_altsetting(winusb_intf, 0); 347 348 /* add the interface to the mass storage function */ 349 rt_usbd_function_add_interface(func, winusb_intf); 350 351 rt_usbd_os_comp_id_desc_add_os_func_comp_id_desc(device->os_comp_id_desc, &winusb_func_comp_id_desc); 352 /* initilize winusb */ 353 rt_usb_winusb_init(func); 354 return func; 355 } 356 357 struct udclass winusb_class = 358 { 359 .rt_usbd_function_create = rt_usbd_function_winusb_create 360 }; 361 362 int rt_usbd_winusb_class_register(void) 363 { 364 rt_usbd_class_register(&winusb_class); 365 return 0; 366 } 367 INIT_PREV_EXPORT(rt_usbd_winusb_class_register); 368