github.com/aykevl/tinygo@v0.5.0/src/machine/usb.go (about) 1 // +build sam 2 3 package machine 4 5 import ( 6 "bytes" 7 "device/sam" 8 "encoding/binary" 9 "errors" 10 ) 11 12 const deviceDescriptorSize = 18 13 14 // DeviceDescriptor implements the USB standard device descriptor. 15 // 16 // Table 9-8. Standard Device Descriptor 17 // bLength, bDescriptorType, bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0, 18 // idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber, bNumConfigurations */ 19 // 20 type DeviceDescriptor struct { 21 bLength uint8 // 18 22 bDescriptorType uint8 // 1 USB_DEVICE_DESCRIPTOR_TYPE 23 bcdUSB uint16 // 0x200 24 bDeviceClass uint8 25 bDeviceSubClass uint8 26 bDeviceProtocol uint8 27 bMaxPacketSize0 uint8 // Packet 0 28 idVendor uint16 29 idProduct uint16 30 bcdDevice uint16 // 0x100 31 iManufacturer uint8 32 iProduct uint8 33 iSerialNumber uint8 34 bNumConfigurations uint8 35 } 36 37 // NewDeviceDescriptor returns a USB DeviceDescriptor. 38 func NewDeviceDescriptor(class, subClass, proto, packetSize0 uint8, vid, pid, version uint16, im, ip, is, configs uint8) DeviceDescriptor { 39 return DeviceDescriptor{deviceDescriptorSize, 1, 0x200, class, subClass, proto, packetSize0, vid, pid, version, im, ip, is, configs} 40 } 41 42 // Bytes returns DeviceDescriptor data 43 func (d DeviceDescriptor) Bytes() []byte { 44 buf := bytes.NewBuffer(make([]byte, 0, deviceDescriptorSize)) 45 binary.Write(buf, binary.LittleEndian, d.bLength) 46 binary.Write(buf, binary.LittleEndian, d.bDescriptorType) 47 binary.Write(buf, binary.LittleEndian, d.bcdUSB) 48 binary.Write(buf, binary.LittleEndian, d.bDeviceClass) 49 binary.Write(buf, binary.LittleEndian, d.bDeviceSubClass) 50 binary.Write(buf, binary.LittleEndian, d.bDeviceProtocol) 51 binary.Write(buf, binary.LittleEndian, d.bMaxPacketSize0) 52 binary.Write(buf, binary.LittleEndian, d.idVendor) 53 binary.Write(buf, binary.LittleEndian, d.idProduct) 54 binary.Write(buf, binary.LittleEndian, d.bcdDevice) 55 binary.Write(buf, binary.LittleEndian, d.iManufacturer) 56 binary.Write(buf, binary.LittleEndian, d.iProduct) 57 binary.Write(buf, binary.LittleEndian, d.iSerialNumber) 58 binary.Write(buf, binary.LittleEndian, d.bNumConfigurations) 59 return buf.Bytes() 60 } 61 62 const configDescriptorSize = 9 63 64 // ConfigDescriptor implements the standard USB configuration descriptor. 65 // 66 // Table 9-10. Standard Configuration Descriptor 67 // bLength, bDescriptorType, wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration 68 // bmAttributes, bMaxPower 69 // 70 type ConfigDescriptor struct { 71 bLength uint8 // 9 72 bDescriptorType uint8 // 2 73 wTotalLength uint16 // total length 74 bNumInterfaces uint8 75 bConfigurationValue uint8 76 iConfiguration uint8 77 bmAttributes uint8 78 bMaxPower uint8 79 } 80 81 // NewConfigDescriptor returns a new USB ConfigDescriptor. 82 func NewConfigDescriptor(totalLength uint16, interfaces uint8) ConfigDescriptor { 83 return ConfigDescriptor{configDescriptorSize, 2, totalLength, interfaces, 1, 0, usb_CONFIG_BUS_POWERED | usb_CONFIG_REMOTE_WAKEUP, 50} 84 } 85 86 // Bytes returns ConfigDescriptor data. 87 func (d ConfigDescriptor) Bytes() []byte { 88 buf := bytes.NewBuffer(make([]byte, 0, configDescriptorSize)) 89 binary.Write(buf, binary.LittleEndian, d.bLength) 90 binary.Write(buf, binary.LittleEndian, d.bDescriptorType) 91 binary.Write(buf, binary.LittleEndian, d.wTotalLength) 92 binary.Write(buf, binary.LittleEndian, d.bNumInterfaces) 93 binary.Write(buf, binary.LittleEndian, d.bConfigurationValue) 94 binary.Write(buf, binary.LittleEndian, d.iConfiguration) 95 binary.Write(buf, binary.LittleEndian, d.bmAttributes) 96 binary.Write(buf, binary.LittleEndian, d.bMaxPower) 97 return buf.Bytes() 98 } 99 100 const interfaceDescriptorSize = 9 101 102 // InterfaceDescriptor implements the standard USB interface descriptor. 103 // 104 // Table 9-12. Standard Interface Descriptor 105 // bLength, bDescriptorType, bInterfaceNumber, bAlternateSetting, bNumEndpoints, bInterfaceClass, 106 // bInterfaceSubClass, bInterfaceProtocol, iInterface 107 // 108 type InterfaceDescriptor struct { 109 bLength uint8 // 9 110 bDescriptorType uint8 // 4 111 bInterfaceNumber uint8 112 bAlternateSetting uint8 113 bNumEndpoints uint8 114 bInterfaceClass uint8 115 bInterfaceSubClass uint8 116 bInterfaceProtocol uint8 117 iInterface uint8 118 } 119 120 // NewInterfaceDescriptor returns a new USB InterfaceDescriptor. 121 func NewInterfaceDescriptor(n, numEndpoints, class, subClass, protocol uint8) InterfaceDescriptor { 122 return InterfaceDescriptor{interfaceDescriptorSize, 4, n, 0, numEndpoints, class, subClass, protocol, 0} 123 } 124 125 // Bytes returns InterfaceDescriptor data. 126 func (d InterfaceDescriptor) Bytes() []byte { 127 buf := bytes.NewBuffer(make([]byte, 0, interfaceDescriptorSize)) 128 binary.Write(buf, binary.LittleEndian, d.bLength) 129 binary.Write(buf, binary.LittleEndian, d.bDescriptorType) 130 binary.Write(buf, binary.LittleEndian, d.bInterfaceNumber) 131 binary.Write(buf, binary.LittleEndian, d.bAlternateSetting) 132 binary.Write(buf, binary.LittleEndian, d.bNumEndpoints) 133 binary.Write(buf, binary.LittleEndian, d.bInterfaceClass) 134 binary.Write(buf, binary.LittleEndian, d.bInterfaceSubClass) 135 binary.Write(buf, binary.LittleEndian, d.bInterfaceProtocol) 136 binary.Write(buf, binary.LittleEndian, d.iInterface) 137 return buf.Bytes() 138 } 139 140 const endpointDescriptorSize = 7 141 142 // EndpointDescriptor implements the standard USB endpoint descriptor. 143 // 144 // Table 9-13. Standard Endpoint Descriptor 145 // bLength, bDescriptorType, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval 146 // 147 type EndpointDescriptor struct { 148 bLength uint8 // 7 149 bDescriptorType uint8 // 5 150 bEndpointAddress uint8 151 bmAttributes uint8 152 wMaxPacketSize uint16 153 bInterval uint8 154 } 155 156 // NewEndpointDescriptor returns a new USB EndpointDescriptor. 157 func NewEndpointDescriptor(addr, attr uint8, packetSize uint16, interval uint8) EndpointDescriptor { 158 return EndpointDescriptor{endpointDescriptorSize, 5, addr, attr, packetSize, interval} 159 } 160 161 // Bytes returns EndpointDescriptor data. 162 func (d EndpointDescriptor) Bytes() []byte { 163 buf := bytes.NewBuffer(make([]byte, 0, endpointDescriptorSize)) 164 binary.Write(buf, binary.LittleEndian, d.bLength) 165 binary.Write(buf, binary.LittleEndian, d.bDescriptorType) 166 binary.Write(buf, binary.LittleEndian, d.bEndpointAddress) 167 binary.Write(buf, binary.LittleEndian, d.bmAttributes) 168 binary.Write(buf, binary.LittleEndian, d.wMaxPacketSize) 169 binary.Write(buf, binary.LittleEndian, d.bInterval) 170 return buf.Bytes() 171 } 172 173 const iadDescriptorSize = 8 174 175 // IADDescriptor is an Interface Association Descriptor, which is used 176 // to bind 2 interfaces together in CDC composite device. 177 // 178 // Standard Interface Association Descriptor: 179 // bLength, bDescriptorType, bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, 180 // bFunctionProtocol, iFunction 181 // 182 type IADDescriptor struct { 183 bLength uint8 // 8 184 bDescriptorType uint8 // 11 185 bFirstInterface uint8 186 bInterfaceCount uint8 187 bFunctionClass uint8 188 bFunctionSubClass uint8 189 bFunctionProtocol uint8 190 iFunction uint8 191 } 192 193 // NewIADDescriptor returns a new USB IADDescriptor. 194 func NewIADDescriptor(firstInterface, count, class, subClass, protocol uint8) IADDescriptor { 195 return IADDescriptor{iadDescriptorSize, 11, firstInterface, count, class, subClass, protocol, 0} 196 } 197 198 // Bytes returns IADDescriptor data. 199 func (d IADDescriptor) Bytes() []byte { 200 buf := bytes.NewBuffer(make([]byte, 0, iadDescriptorSize)) 201 binary.Write(buf, binary.LittleEndian, d.bLength) 202 binary.Write(buf, binary.LittleEndian, d.bDescriptorType) 203 binary.Write(buf, binary.LittleEndian, d.bFirstInterface) 204 binary.Write(buf, binary.LittleEndian, d.bInterfaceCount) 205 binary.Write(buf, binary.LittleEndian, d.bFunctionClass) 206 binary.Write(buf, binary.LittleEndian, d.bFunctionSubClass) 207 binary.Write(buf, binary.LittleEndian, d.bFunctionProtocol) 208 binary.Write(buf, binary.LittleEndian, d.iFunction) 209 return buf.Bytes() 210 } 211 212 const cdcCSInterfaceDescriptorSize = 5 213 214 // CDCCSInterfaceDescriptor is a CDC CS interface descriptor. 215 type CDCCSInterfaceDescriptor struct { 216 len uint8 // 5 217 dtype uint8 // 0x24 218 subtype uint8 219 d0 uint8 220 d1 uint8 221 } 222 223 // NewCDCCSInterfaceDescriptor returns a new USB CDCCSInterfaceDescriptor. 224 func NewCDCCSInterfaceDescriptor(subtype, d0, d1 uint8) CDCCSInterfaceDescriptor { 225 return CDCCSInterfaceDescriptor{cdcCSInterfaceDescriptorSize, 0x24, subtype, d0, d1} 226 } 227 228 // Bytes returns CDCCSInterfaceDescriptor data. 229 func (d CDCCSInterfaceDescriptor) Bytes() []byte { 230 buf := bytes.NewBuffer(make([]byte, 0, cdcCSInterfaceDescriptorSize)) 231 binary.Write(buf, binary.LittleEndian, d.len) 232 binary.Write(buf, binary.LittleEndian, d.dtype) 233 binary.Write(buf, binary.LittleEndian, d.subtype) 234 binary.Write(buf, binary.LittleEndian, d.d0) 235 binary.Write(buf, binary.LittleEndian, d.d1) 236 return buf.Bytes() 237 } 238 239 const cmFunctionalDescriptorSize = 5 240 241 // CMFunctionalDescriptor is the functional descriptor general format. 242 type CMFunctionalDescriptor struct { 243 bFunctionLength uint8 244 bDescriptorType uint8 // 0x24 245 bDescriptorSubtype uint8 // 1 246 bmCapabilities uint8 247 bDataInterface uint8 248 } 249 250 // NewCMFunctionalDescriptor returns a new USB CMFunctionalDescriptor. 251 func NewCMFunctionalDescriptor(subtype, d0, d1 uint8) CMFunctionalDescriptor { 252 return CMFunctionalDescriptor{5, 0x24, subtype, d0, d1} 253 } 254 255 // Bytes returns the CMFunctionalDescriptor data. 256 func (d CMFunctionalDescriptor) Bytes() []byte { 257 buf := bytes.NewBuffer(make([]byte, 0, cmFunctionalDescriptorSize)) 258 binary.Write(buf, binary.LittleEndian, d.bFunctionLength) 259 binary.Write(buf, binary.LittleEndian, d.bDescriptorType) 260 binary.Write(buf, binary.LittleEndian, d.bDescriptorSubtype) 261 binary.Write(buf, binary.LittleEndian, d.bmCapabilities) 262 binary.Write(buf, binary.LittleEndian, d.bDataInterface) 263 return buf.Bytes() 264 } 265 266 const acmFunctionalDescriptorSize = 4 267 268 // ACMFunctionalDescriptor is a Abstract Control Model (ACM) USB descriptor. 269 type ACMFunctionalDescriptor struct { 270 len uint8 271 dtype uint8 // 0x24 272 subtype uint8 // 1 273 bmCapabilities uint8 274 } 275 276 // NewACMFunctionalDescriptor returns a new USB ACMFunctionalDescriptor. 277 func NewACMFunctionalDescriptor(subtype, d0 uint8) ACMFunctionalDescriptor { 278 return ACMFunctionalDescriptor{4, 0x24, subtype, d0} 279 } 280 281 // Bytes returns the ACMFunctionalDescriptor data. 282 func (d ACMFunctionalDescriptor) Bytes() []byte { 283 buf := bytes.NewBuffer(make([]byte, 0, acmFunctionalDescriptorSize)) 284 binary.Write(buf, binary.LittleEndian, d.len) 285 binary.Write(buf, binary.LittleEndian, d.dtype) 286 binary.Write(buf, binary.LittleEndian, d.subtype) 287 binary.Write(buf, binary.LittleEndian, d.bmCapabilities) 288 return buf.Bytes() 289 } 290 291 // CDCDescriptor is the Communication Device Class (CDC) descriptor. 292 type CDCDescriptor struct { 293 // IAD 294 iad IADDescriptor // Only needed on compound device 295 296 // Control 297 cif InterfaceDescriptor 298 header CDCCSInterfaceDescriptor 299 300 // CDC control 301 controlManagement ACMFunctionalDescriptor // ACM 302 functionalDescriptor CDCCSInterfaceDescriptor // CDC_UNION 303 callManagement CMFunctionalDescriptor // Call Management 304 cifin EndpointDescriptor 305 306 // CDC Data 307 dif InterfaceDescriptor 308 in EndpointDescriptor 309 out EndpointDescriptor 310 } 311 312 func NewCDCDescriptor(i IADDescriptor, c InterfaceDescriptor, 313 h CDCCSInterfaceDescriptor, 314 cm ACMFunctionalDescriptor, 315 fd CDCCSInterfaceDescriptor, 316 callm CMFunctionalDescriptor, 317 ci EndpointDescriptor, 318 di InterfaceDescriptor, 319 inp EndpointDescriptor, 320 outp EndpointDescriptor) CDCDescriptor { 321 return CDCDescriptor{iad: i, 322 cif: c, 323 header: h, 324 controlManagement: cm, 325 functionalDescriptor: fd, 326 callManagement: callm, 327 cifin: ci, 328 dif: di, 329 in: inp, 330 out: outp} 331 } 332 333 const cdcSize = iadDescriptorSize + 334 interfaceDescriptorSize + 335 cdcCSInterfaceDescriptorSize + 336 acmFunctionalDescriptorSize + 337 cdcCSInterfaceDescriptorSize + 338 cmFunctionalDescriptorSize + 339 endpointDescriptorSize + 340 interfaceDescriptorSize + 341 endpointDescriptorSize + 342 endpointDescriptorSize 343 344 // Bytes returns CDCDescriptor data. 345 func (d CDCDescriptor) Bytes() []byte { 346 buf := bytes.NewBuffer(make([]byte, 0, cdcSize)) 347 buf.Write(d.iad.Bytes()) 348 buf.Write(d.cif.Bytes()) 349 buf.Write(d.header.Bytes()) 350 buf.Write(d.controlManagement.Bytes()) 351 buf.Write(d.functionalDescriptor.Bytes()) 352 buf.Write(d.callManagement.Bytes()) 353 buf.Write(d.cifin.Bytes()) 354 buf.Write(d.dif.Bytes()) 355 buf.Write(d.in.Bytes()) 356 buf.Write(d.out.Bytes()) 357 return buf.Bytes() 358 } 359 360 // MSCDescriptor is not used yet. 361 type MSCDescriptor struct { 362 msc InterfaceDescriptor 363 in EndpointDescriptor 364 out EndpointDescriptor 365 } 366 367 type cdcLineInfo struct { 368 dwDTERate uint32 369 bCharFormat uint8 370 bParityType uint8 371 bDataBits uint8 372 lineState uint8 373 } 374 375 var ( 376 // TODO: allow setting these 377 usb_STRING_LANGUAGE = [2]uint16{(3 << 8) | (2 + 2), 0x0409} // English 378 usb_STRING_PRODUCT = "Arduino Zero" 379 usb_STRING_MANUFACTURER = "Arduino" 380 381 usb_VID uint16 = 0x2341 382 usb_PID uint16 = 0x004d 383 ) 384 385 const ( 386 usb_IMANUFACTURER = 1 387 usb_IPRODUCT = 2 388 usb_ISERIAL = 3 389 390 usb_ENDPOINT_TYPE_CONTROL = 0x00 391 usb_ENDPOINT_TYPE_ISOCHRONOUS = 0x01 392 usb_ENDPOINT_TYPE_BULK = 0x02 393 usb_ENDPOINT_TYPE_INTERRUPT = 0x03 394 395 usb_DEVICE_DESCRIPTOR_TYPE = 1 396 usb_CONFIGURATION_DESCRIPTOR_TYPE = 2 397 usb_STRING_DESCRIPTOR_TYPE = 3 398 usb_INTERFACE_DESCRIPTOR_TYPE = 4 399 usb_ENDPOINT_DESCRIPTOR_TYPE = 5 400 usb_DEVICE_QUALIFIER = 6 401 usb_OTHER_SPEED_CONFIGURATION = 7 402 403 usbEndpointOut = 0x00 404 usbEndpointIn = 0x80 405 406 usbEndpointPacketSize = 64 // 64 for Full Speed, EPT size max is 1024 407 usb_EPT_NUM = 7 408 409 // standard requests 410 usb_GET_STATUS = 0 411 usb_CLEAR_FEATURE = 1 412 usb_SET_FEATURE = 3 413 usb_SET_ADDRESS = 5 414 usb_GET_DESCRIPTOR = 6 415 usb_SET_DESCRIPTOR = 7 416 usb_GET_CONFIGURATION = 8 417 usb_SET_CONFIGURATION = 9 418 usb_GET_INTERFACE = 10 419 usb_SET_INTERFACE = 11 420 421 usb_DEVICE_CLASS_COMMUNICATIONS = 0x02 422 usb_DEVICE_CLASS_HUMAN_INTERFACE = 0x03 423 usb_DEVICE_CLASS_STORAGE = 0x08 424 usb_DEVICE_CLASS_VENDOR_SPECIFIC = 0xFF 425 426 usb_CONFIG_POWERED_MASK = 0x40 427 usb_CONFIG_BUS_POWERED = 0x80 428 usb_CONFIG_SELF_POWERED = 0xC0 429 usb_CONFIG_REMOTE_WAKEUP = 0x20 430 431 // CDC 432 usb_CDC_ACM_INTERFACE = 0 // CDC ACM 433 usb_CDC_DATA_INTERFACE = 1 // CDC Data 434 usb_CDC_FIRST_ENDPOINT = 1 435 usb_CDC_ENDPOINT_ACM = 1 436 usb_CDC_ENDPOINT_OUT = 2 437 usb_CDC_ENDPOINT_IN = 3 438 439 // bmRequestType 440 usb_REQUEST_HOSTTODEVICE = 0x00 441 usb_REQUEST_DEVICETOHOST = 0x80 442 usb_REQUEST_DIRECTION = 0x80 443 444 usb_REQUEST_STANDARD = 0x00 445 usb_REQUEST_CLASS = 0x20 446 usb_REQUEST_VENDOR = 0x40 447 usb_REQUEST_TYPE = 0x60 448 449 usb_REQUEST_DEVICE = 0x00 450 usb_REQUEST_INTERFACE = 0x01 451 usb_REQUEST_ENDPOINT = 0x02 452 usb_REQUEST_OTHER = 0x03 453 usb_REQUEST_RECIPIENT = 0x1F 454 455 usb_REQUEST_DEVICETOHOST_CLASS_INTERFACE = (usb_REQUEST_DEVICETOHOST | usb_REQUEST_CLASS | usb_REQUEST_INTERFACE) 456 usb_REQUEST_HOSTTODEVICE_CLASS_INTERFACE = (usb_REQUEST_HOSTTODEVICE | usb_REQUEST_CLASS | usb_REQUEST_INTERFACE) 457 usb_REQUEST_DEVICETOHOST_STANDARD_INTERFACE = (usb_REQUEST_DEVICETOHOST | usb_REQUEST_STANDARD | usb_REQUEST_INTERFACE) 458 459 // CDC Class requests 460 usb_CDC_SET_LINE_CODING = 0x20 461 usb_CDC_GET_LINE_CODING = 0x21 462 usb_CDC_SET_CONTROL_LINE_STATE = 0x22 463 usb_CDC_SEND_BREAK = 0x23 464 465 usb_CDC_V1_10 = 0x0110 466 usb_CDC_COMMUNICATION_INTERFACE_CLASS = 0x02 467 468 usb_CDC_CALL_MANAGEMENT = 0x01 469 usb_CDC_ABSTRACT_CONTROL_MODEL = 0x02 470 usb_CDC_HEADER = 0x00 471 usb_CDC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 472 usb_CDC_UNION = 0x06 473 usb_CDC_CS_INTERFACE = 0x24 474 usb_CDC_CS_ENDPOINT = 0x25 475 usb_CDC_DATA_INTERFACE_CLASS = 0x0A 476 ) 477 478 // usbDeviceDescBank is the USB device endpoint descriptor. 479 // typedef struct { 480 // __IO USB_DEVICE_ADDR_Type ADDR; /**< \brief Offset: 0x000 (R/W 32) DEVICE_DESC_BANK Endpoint Bank, Adress of Data Buffer */ 481 // __IO USB_DEVICE_PCKSIZE_Type PCKSIZE; /**< \brief Offset: 0x004 (R/W 32) DEVICE_DESC_BANK Endpoint Bank, Packet Size */ 482 // __IO USB_DEVICE_EXTREG_Type EXTREG; /**< \brief Offset: 0x008 (R/W 16) DEVICE_DESC_BANK Endpoint Bank, Extended */ 483 // __IO USB_DEVICE_STATUS_BK_Type STATUS_BK; /**< \brief Offset: 0x00A (R/W 8) DEVICE_DESC_BANK Enpoint Bank, Status of Bank */ 484 // RoReg8 Reserved1[0x5]; 485 // } UsbDeviceDescBank; 486 type usbDeviceDescBank struct { 487 ADDR sam.RegValue 488 PCKSIZE sam.RegValue 489 EXTREG sam.RegValue16 490 STATUS_BK sam.RegValue8 491 _reserved [5]sam.RegValue8 492 } 493 494 type usbDeviceDescriptor struct { 495 DeviceDescBank [2]usbDeviceDescBank 496 } 497 498 // typedef struct { 499 // union { 500 // uint8_t bmRequestType; 501 // struct { 502 // uint8_t direction : 5; 503 // uint8_t type : 2; 504 // uint8_t transferDirection : 1; 505 // }; 506 // }; 507 // uint8_t bRequest; 508 // uint8_t wValueL; 509 // uint8_t wValueH; 510 // uint16_t wIndex; 511 // uint16_t wLength; 512 // } USBSetup; 513 type usbSetup struct { 514 bmRequestType uint8 515 bRequest uint8 516 wValueL uint8 517 wValueH uint8 518 wIndex uint16 519 wLength uint16 520 } 521 522 func newUSBSetup(data []byte) usbSetup { 523 buf := bytes.NewBuffer(data) 524 u := usbSetup{} 525 binary.Read(buf, binary.LittleEndian, &(u.bmRequestType)) 526 binary.Read(buf, binary.LittleEndian, &(u.bRequest)) 527 binary.Read(buf, binary.LittleEndian, &(u.wValueL)) 528 binary.Read(buf, binary.LittleEndian, &(u.wValueH)) 529 binary.Read(buf, binary.LittleEndian, &(u.wIndex)) 530 binary.Read(buf, binary.LittleEndian, &(u.wLength)) 531 return u 532 } 533 534 // USBCDC is the serial interface that works over the USB port. 535 // To implement the USBCDC interface for a board, you must declare a concrete type as follows: 536 // 537 // type USBCDC struct { 538 // Buffer *RingBuffer 539 // } 540 // 541 // You can also add additional members to this struct depending on your implementation, 542 // but the *RingBuffer is required. 543 // When you are declaring the USBCDC for your board, make sure that you also declare the 544 // RingBuffer using the NewRingBuffer() function: 545 // 546 // USBCDC{Buffer: NewRingBuffer()} 547 // 548 549 // Read from the RX buffer. 550 func (usbcdc USBCDC) Read(data []byte) (n int, err error) { 551 // check if RX buffer is empty 552 size := usbcdc.Buffered() 553 if size == 0 { 554 return 0, nil 555 } 556 557 // Make sure we do not read more from buffer than the data slice can hold. 558 if len(data) < size { 559 size = len(data) 560 } 561 562 // only read number of bytes used from buffer 563 for i := 0; i < size; i++ { 564 v, _ := usbcdc.ReadByte() 565 data[i] = v 566 } 567 568 return size, nil 569 } 570 571 // Write data to the USBCDC. 572 func (usbcdc USBCDC) Write(data []byte) (n int, err error) { 573 for _, v := range data { 574 usbcdc.WriteByte(v) 575 } 576 return len(data), nil 577 } 578 579 // ReadByte reads a single byte from the RX buffer. 580 // If there is no data in the buffer, returns an error. 581 func (usbcdc USBCDC) ReadByte() (byte, error) { 582 // check if RX buffer is empty 583 buf, ok := usbcdc.Buffer.Get() 584 if !ok { 585 return 0, errors.New("Buffer empty") 586 } 587 return buf, nil 588 } 589 590 // Buffered returns the number of bytes currently stored in the RX buffer. 591 func (usbcdc USBCDC) Buffered() int { 592 return int(usbcdc.Buffer.Used()) 593 } 594 595 // Receive handles adding data to the UART's data buffer. 596 // Usually called by the IRQ handler for a machine. 597 func (usbcdc USBCDC) Receive(data byte) { 598 usbcdc.Buffer.Put(data) 599 }