machine/atsamd21,atsamd51,nrf52840: refactor USB CDC device descriptor to reduce code duplication and heap allocations
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Этот коммит содержится в:
		
							родитель
							
								
									06797b6d1a
								
							
						
					
					
						коммит
						03fa9dd9b7
					
				
					 4 изменённых файлов: 120 добавлений и 324 удалений
				
			
		|  | @ -1478,7 +1478,7 @@ func handleUSB(intr interrupt.Interrupt) { | |||
| 			setEPINTENCLR(0, sam.USB_DEVICE_EPINTENCLR_STALL1) | ||||
| 		} | ||||
| 	} else { | ||||
| 		sendZlp(0) | ||||
| 		sendZlp() | ||||
| 	} | ||||
| 
 | ||||
| 	// Now the actual transfer handlers, ignore endpoint number 0 (setup) | ||||
|  | @ -1601,7 +1601,7 @@ func handleStandardSetup(setup usbSetup) bool { | |||
| 		} else if setup.wValueL == 0 { // ENDPOINTHALT | ||||
| 			isEndpointHalt = false | ||||
| 		} | ||||
| 		sendZlp(0) | ||||
| 		sendZlp() | ||||
| 		return true | ||||
| 
 | ||||
| 	case usb_SET_FEATURE: | ||||
|  | @ -1610,7 +1610,7 @@ func handleStandardSetup(setup usbSetup) bool { | |||
| 		} else if setup.wValueL == 0 { // ENDPOINTHALT | ||||
| 			isEndpointHalt = true | ||||
| 		} | ||||
| 		sendZlp(0) | ||||
| 		sendZlp() | ||||
| 		return true | ||||
| 
 | ||||
| 	case usb_SET_ADDRESS: | ||||
|  | @ -1665,7 +1665,7 @@ func handleStandardSetup(setup usbSetup) bool { | |||
| 			// Enable interrupt for CDC data messages from host | ||||
| 			setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_EPINTENSET_TRCPT0) | ||||
| 
 | ||||
| 			sendZlp(0) | ||||
| 			sendZlp() | ||||
| 			return true | ||||
| 		} else { | ||||
| 			return false | ||||
|  | @ -1679,7 +1679,7 @@ func handleStandardSetup(setup usbSetup) bool { | |||
| 	case usb_SET_INTERFACE: | ||||
| 		usbSetInterface = setup.wValueL | ||||
| 
 | ||||
| 		sendZlp(0) | ||||
| 		sendZlp() | ||||
| 		return true | ||||
| 
 | ||||
| 	default: | ||||
|  | @ -1724,14 +1724,14 @@ func cdcSetup(setup usbSetup) bool { | |||
| 			} else { | ||||
| 				// TODO: cancel any reset | ||||
| 			} | ||||
| 			sendZlp(0) | ||||
| 			sendZlp() | ||||
| 		} | ||||
| 
 | ||||
| 		if setup.bRequest == usb_CDC_SEND_BREAK { | ||||
| 			// TODO: something with this value? | ||||
| 			// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; | ||||
| 			// return false; | ||||
| 			sendZlp(0) | ||||
| 			sendZlp() | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
|  | @ -1790,104 +1790,6 @@ func receiveUSBControlPacket() []byte { | |||
| 	return data | ||||
| } | ||||
| 
 | ||||
| // sendDescriptor creates and sends the various USB descriptor types that | ||||
| // can be requested by the host. | ||||
| func sendDescriptor(setup usbSetup) { | ||||
| 	switch setup.wValueH { | ||||
| 	case usb_CONFIGURATION_DESCRIPTOR_TYPE: | ||||
| 		sendConfiguration(setup) | ||||
| 		return | ||||
| 	case usb_DEVICE_DESCRIPTOR_TYPE: | ||||
| 		// composite descriptor | ||||
| 		dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1) | ||||
| 		l := deviceDescriptorSize | ||||
| 		if setup.wLength < deviceDescriptorSize { | ||||
| 			l = int(setup.wLength) | ||||
| 		} | ||||
| 		sendUSBPacket(0, dd.Bytes()[:l]) | ||||
| 		return | ||||
| 
 | ||||
| 	case usb_STRING_DESCRIPTOR_TYPE: | ||||
| 		switch setup.wValueL { | ||||
| 		case 0: | ||||
| 			b := []byte{0x04, 0x03, 0x09, 0x04} | ||||
| 			sendUSBPacket(0, b) | ||||
| 			return | ||||
| 
 | ||||
| 		case usb_IPRODUCT: | ||||
| 			b := strToUTF16LEDescriptor(usb_STRING_PRODUCT) | ||||
| 			sendUSBPacket(0, b) | ||||
| 			return | ||||
| 
 | ||||
| 		case usb_IMANUFACTURER: | ||||
| 			b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER) | ||||
| 			sendUSBPacket(0, b) | ||||
| 			return | ||||
| 
 | ||||
| 		case usb_ISERIAL: | ||||
| 			// TODO: allow returning a product serial number | ||||
| 			sendZlp(0) | ||||
| 		} | ||||
| 
 | ||||
| 		// send final zero length packet and return | ||||
| 		sendZlp(0) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// do not know how to handle this message, so return zero | ||||
| 	sendZlp(0) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // sendConfiguration creates and sends the configuration packet to the host. | ||||
| func sendConfiguration(setup usbSetup) { | ||||
| 	if setup.wLength == 9 { | ||||
| 		sz := uint16(configDescriptorSize + cdcSize) | ||||
| 		config := NewConfigDescriptor(sz, 2) | ||||
| 		sendUSBPacket(0, config.Bytes()) | ||||
| 	} else { | ||||
| 		iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) | ||||
| 
 | ||||
| 		cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) | ||||
| 
 | ||||
| 		header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF) | ||||
| 
 | ||||
| 		controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6) | ||||
| 
 | ||||
| 		functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE) | ||||
| 
 | ||||
| 		callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1) | ||||
| 
 | ||||
| 		cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10) | ||||
| 
 | ||||
| 		dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0) | ||||
| 
 | ||||
| 		out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) | ||||
| 
 | ||||
| 		in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) | ||||
| 
 | ||||
| 		cdc := NewCDCDescriptor(iad, | ||||
| 			cif, | ||||
| 			header, | ||||
| 			controlManagement, | ||||
| 			functionalDescriptor, | ||||
| 			callManagement, | ||||
| 			cifin, | ||||
| 			dif, | ||||
| 			out, | ||||
| 			in) | ||||
| 
 | ||||
| 		sz := uint16(configDescriptorSize + cdcSize) | ||||
| 		config := NewConfigDescriptor(sz, 2) | ||||
| 
 | ||||
| 		buf := make([]byte, 0, sz) | ||||
| 		buf = append(buf, config.Bytes()...) | ||||
| 		buf = append(buf, cdc.Bytes()...) | ||||
| 
 | ||||
| 		sendUSBPacket(0, buf) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func handleEndpoint(ep uint32) { | ||||
| 	// get data | ||||
| 	count := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >> | ||||
|  | @ -1908,8 +1810,8 @@ func handleEndpoint(ep uint32) { | |||
| 	setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY) | ||||
| } | ||||
| 
 | ||||
| func sendZlp(ep uint32) { | ||||
| 	usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) | ||||
| func sendZlp() { | ||||
| 	usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) | ||||
| } | ||||
| 
 | ||||
| func epPacketSize(size uint16) uint32 { | ||||
|  |  | |||
|  | @ -1649,7 +1649,7 @@ func handleUSBIRQ(interrupt.Interrupt) { | |||
| 			setEPINTENCLR(0, sam.USB_DEVICE_ENDPOINT_EPINTENCLR_STALL1) | ||||
| 		} | ||||
| 	} else { | ||||
| 		sendZlp(0) | ||||
| 		sendZlp() | ||||
| 	} | ||||
| 
 | ||||
| 	// Now the actual transfer handlers, ignore endpoint number 0 (setup) | ||||
|  | @ -1772,7 +1772,7 @@ func handleStandardSetup(setup usbSetup) bool { | |||
| 		} else if setup.wValueL == 0 { // ENDPOINTHALT | ||||
| 			isEndpointHalt = false | ||||
| 		} | ||||
| 		sendZlp(0) | ||||
| 		sendZlp() | ||||
| 		return true | ||||
| 
 | ||||
| 	case usb_SET_FEATURE: | ||||
|  | @ -1781,7 +1781,7 @@ func handleStandardSetup(setup usbSetup) bool { | |||
| 		} else if setup.wValueL == 0 { // ENDPOINTHALT | ||||
| 			isEndpointHalt = true | ||||
| 		} | ||||
| 		sendZlp(0) | ||||
| 		sendZlp() | ||||
| 		return true | ||||
| 
 | ||||
| 	case usb_SET_ADDRESS: | ||||
|  | @ -1836,7 +1836,7 @@ func handleStandardSetup(setup usbSetup) bool { | |||
| 			// Enable interrupt for CDC data messages from host | ||||
| 			setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0) | ||||
| 
 | ||||
| 			sendZlp(0) | ||||
| 			sendZlp() | ||||
| 			return true | ||||
| 		} else { | ||||
| 			return false | ||||
|  | @ -1850,7 +1850,7 @@ func handleStandardSetup(setup usbSetup) bool { | |||
| 	case usb_SET_INTERFACE: | ||||
| 		usbSetInterface = setup.wValueL | ||||
| 
 | ||||
| 		sendZlp(0) | ||||
| 		sendZlp() | ||||
| 		return true | ||||
| 
 | ||||
| 	default: | ||||
|  | @ -1895,14 +1895,14 @@ func cdcSetup(setup usbSetup) bool { | |||
| 			} else { | ||||
| 				// TODO: cancel any reset | ||||
| 			} | ||||
| 			sendZlp(0) | ||||
| 			sendZlp() | ||||
| 		} | ||||
| 
 | ||||
| 		if setup.bRequest == usb_CDC_SEND_BREAK { | ||||
| 			// TODO: something with this value? | ||||
| 			// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; | ||||
| 			// return false; | ||||
| 			sendZlp(0) | ||||
| 			sendZlp() | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
|  | @ -1961,104 +1961,6 @@ func receiveUSBControlPacket() []byte { | |||
| 	return data | ||||
| } | ||||
| 
 | ||||
| // sendDescriptor creates and sends the various USB descriptor types that | ||||
| // can be requested by the host. | ||||
| func sendDescriptor(setup usbSetup) { | ||||
| 	switch setup.wValueH { | ||||
| 	case usb_CONFIGURATION_DESCRIPTOR_TYPE: | ||||
| 		sendConfiguration(setup) | ||||
| 		return | ||||
| 	case usb_DEVICE_DESCRIPTOR_TYPE: | ||||
| 		// composite descriptor | ||||
| 		dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1) | ||||
| 		l := deviceDescriptorSize | ||||
| 		if setup.wLength < deviceDescriptorSize { | ||||
| 			l = int(setup.wLength) | ||||
| 		} | ||||
| 		sendUSBPacket(0, dd.Bytes()[:l]) | ||||
| 		return | ||||
| 
 | ||||
| 	case usb_STRING_DESCRIPTOR_TYPE: | ||||
| 		switch setup.wValueL { | ||||
| 		case 0: | ||||
| 			b := []byte{0x04, 0x03, 0x09, 0x04} | ||||
| 			sendUSBPacket(0, b) | ||||
| 			return | ||||
| 
 | ||||
| 		case usb_IPRODUCT: | ||||
| 			b := strToUTF16LEDescriptor(usb_STRING_PRODUCT) | ||||
| 			sendUSBPacket(0, b) | ||||
| 			return | ||||
| 
 | ||||
| 		case usb_IMANUFACTURER: | ||||
| 			b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER) | ||||
| 			sendUSBPacket(0, b) | ||||
| 			return | ||||
| 
 | ||||
| 		case usb_ISERIAL: | ||||
| 			// TODO: allow returning a product serial number | ||||
| 			sendZlp(0) | ||||
| 		} | ||||
| 
 | ||||
| 		// send final zero length packet and return | ||||
| 		sendZlp(0) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// do not know how to handle this message, so return zero | ||||
| 	sendZlp(0) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // sendConfiguration creates and sends the configuration packet to the host. | ||||
| func sendConfiguration(setup usbSetup) { | ||||
| 	if setup.wLength == 9 { | ||||
| 		sz := uint16(configDescriptorSize + cdcSize) | ||||
| 		config := NewConfigDescriptor(sz, 2) | ||||
| 		sendUSBPacket(0, config.Bytes()) | ||||
| 	} else { | ||||
| 		iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) | ||||
| 
 | ||||
| 		cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) | ||||
| 
 | ||||
| 		header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF) | ||||
| 
 | ||||
| 		controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6) | ||||
| 
 | ||||
| 		functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE) | ||||
| 
 | ||||
| 		callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1) | ||||
| 
 | ||||
| 		cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10) | ||||
| 
 | ||||
| 		dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0) | ||||
| 
 | ||||
| 		out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) | ||||
| 
 | ||||
| 		in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) | ||||
| 
 | ||||
| 		cdc := NewCDCDescriptor(iad, | ||||
| 			cif, | ||||
| 			header, | ||||
| 			controlManagement, | ||||
| 			functionalDescriptor, | ||||
| 			callManagement, | ||||
| 			cifin, | ||||
| 			dif, | ||||
| 			out, | ||||
| 			in) | ||||
| 
 | ||||
| 		sz := uint16(configDescriptorSize + cdcSize) | ||||
| 		config := NewConfigDescriptor(sz, 2) | ||||
| 
 | ||||
| 		buf := make([]byte, 0) | ||||
| 		buf = append(buf, config.Bytes()...) | ||||
| 		buf = append(buf, cdc.Bytes()...) | ||||
| 
 | ||||
| 		sendUSBPacket(0, buf) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func handleEndpoint(ep uint32) { | ||||
| 	// get data | ||||
| 	count := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >> | ||||
|  | @ -2079,8 +1981,8 @@ func handleEndpoint(ep uint32) { | |||
| 	setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY) | ||||
| } | ||||
| 
 | ||||
| func sendZlp(ep uint32) { | ||||
| 	usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) | ||||
| func sendZlp() { | ||||
| 	usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) | ||||
| } | ||||
| 
 | ||||
| func epPacketSize(size uint16) uint32 { | ||||
|  |  | |||
|  | @ -381,16 +381,14 @@ type cdcLineInfo struct { | |||
| // to do a "proper" conversion, we would need to pull in the 'unicode/utf16' | ||||
| // package, which at the time this was written added 512 bytes to the compiled | ||||
| // binary. | ||||
| func strToUTF16LEDescriptor(in string) []byte { | ||||
| 	size := (len(in) << 1) + 2 | ||||
| 	out := make([]byte, size) | ||||
| 	out[0] = byte(size) | ||||
| 	out[1] = 0x03 | ||||
| func strToUTF16LEDescriptor(in string, out []byte) { | ||||
| 	out[0] = byte(len(out)) | ||||
| 	out[1] = usb_STRING_DESCRIPTOR_TYPE | ||||
| 	for i, rune := range in { | ||||
| 		out[(i<<1)+2] = byte(rune) | ||||
| 		out[(i<<1)+3] = 0 | ||||
| 	} | ||||
| 	return out | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
|  | @ -615,3 +613,97 @@ func (usbcdc USBCDC) Buffered() int { | |||
| func (usbcdc USBCDC) Receive(data byte) { | ||||
| 	usbcdc.Buffer.Put(data) | ||||
| } | ||||
| 
 | ||||
| // sendDescriptor creates and sends the various USB descriptor types that | ||||
| // can be requested by the host. | ||||
| func sendDescriptor(setup usbSetup) { | ||||
| 	switch setup.wValueH { | ||||
| 	case usb_CONFIGURATION_DESCRIPTOR_TYPE: | ||||
| 		sendConfiguration(setup) | ||||
| 		return | ||||
| 	case usb_DEVICE_DESCRIPTOR_TYPE: | ||||
| 		// composite descriptor | ||||
| 		dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1) | ||||
| 		l := deviceDescriptorSize | ||||
| 		if setup.wLength < deviceDescriptorSize { | ||||
| 			l = int(setup.wLength) | ||||
| 		} | ||||
| 		sendUSBPacket(0, dd.Bytes()[:l]) | ||||
| 		return | ||||
| 
 | ||||
| 	case usb_STRING_DESCRIPTOR_TYPE: | ||||
| 		switch setup.wValueL { | ||||
| 		case 0: | ||||
| 			b := []byte{0x04, 0x03, 0x09, 0x04} | ||||
| 			sendUSBPacket(0, b) | ||||
| 
 | ||||
| 		case usb_IPRODUCT: | ||||
| 			b := make([]byte, (len(usb_STRING_PRODUCT)<<1)+2) | ||||
| 			strToUTF16LEDescriptor(usb_STRING_PRODUCT, b) | ||||
| 			sendUSBPacket(0, b) | ||||
| 
 | ||||
| 		case usb_IMANUFACTURER: | ||||
| 			b := make([]byte, (len(usb_STRING_MANUFACTURER)<<1)+2) | ||||
| 			strToUTF16LEDescriptor(usb_STRING_MANUFACTURER, b) | ||||
| 			sendUSBPacket(0, b) | ||||
| 
 | ||||
| 		case usb_ISERIAL: | ||||
| 			// TODO: allow returning a product serial number | ||||
| 			sendZlp() | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// do not know how to handle this message, so return zero | ||||
| 	sendZlp() | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // sendConfiguration creates and sends the configuration packet to the host. | ||||
| func sendConfiguration(setup usbSetup) { | ||||
| 	if setup.wLength == 9 { | ||||
| 		sz := uint16(configDescriptorSize + cdcSize) | ||||
| 		config := NewConfigDescriptor(sz, 2) | ||||
| 		sendUSBPacket(0, config.Bytes()) | ||||
| 	} else { | ||||
| 		iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) | ||||
| 
 | ||||
| 		cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) | ||||
| 
 | ||||
| 		header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF) | ||||
| 
 | ||||
| 		controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6) | ||||
| 
 | ||||
| 		functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE) | ||||
| 
 | ||||
| 		callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1) | ||||
| 
 | ||||
| 		cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10) | ||||
| 
 | ||||
| 		dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0) | ||||
| 
 | ||||
| 		out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) | ||||
| 
 | ||||
| 		in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) | ||||
| 
 | ||||
| 		cdc := NewCDCDescriptor(iad, | ||||
| 			cif, | ||||
| 			header, | ||||
| 			controlManagement, | ||||
| 			functionalDescriptor, | ||||
| 			callManagement, | ||||
| 			cifin, | ||||
| 			dif, | ||||
| 			out, | ||||
| 			in) | ||||
| 
 | ||||
| 		sz := uint16(configDescriptorSize + cdcSize) | ||||
| 		config := NewConfigDescriptor(sz, 2) | ||||
| 
 | ||||
| 		buf := make([]byte, 0, sz) | ||||
| 		buf = append(buf, config.Bytes()...) | ||||
| 		buf = append(buf, cdc.Bytes()...) | ||||
| 
 | ||||
| 		sendUSBPacket(0, buf) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -400,110 +400,6 @@ func sendUSBPacket(ep uint32, data []byte) { | |||
| 	) | ||||
| } | ||||
| 
 | ||||
| // sendDescriptor creates and sends the various USB descriptor types that | ||||
| // can be requested by the host. | ||||
| func sendDescriptor(setup usbSetup) { | ||||
| 	switch setup.wValueH { | ||||
| 	case usb_CONFIGURATION_DESCRIPTOR_TYPE: | ||||
| 		sendConfiguration(setup) | ||||
| 		return | ||||
| 	case usb_DEVICE_DESCRIPTOR_TYPE: | ||||
| 		// composite descriptor | ||||
| 		dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1) | ||||
| 		l := deviceDescriptorSize | ||||
| 		if setup.wLength < deviceDescriptorSize { | ||||
| 			l = int(setup.wLength) | ||||
| 		} | ||||
| 		sendUSBPacket(0, dd.Bytes()[:l]) | ||||
| 		return | ||||
| 
 | ||||
| 	case usb_STRING_DESCRIPTOR_TYPE: | ||||
| 		switch setup.wValueL { | ||||
| 		case 0: | ||||
| 			b := make([]byte, 4) | ||||
| 			b[0] = 0x04 | ||||
| 			b[1] = 0x03 | ||||
| 			b[2] = 0x09 | ||||
| 			b[3] = 0x04 | ||||
| 			sendUSBPacket(0, b) | ||||
| 
 | ||||
| 		case usb_IPRODUCT: | ||||
| 			b := strToUTF16LEDescriptor(usb_STRING_PRODUCT) | ||||
| 			if setup.wLength == 2 { | ||||
| 				sendUSBPacket(0, b[:2]) | ||||
| 			} else { | ||||
| 				sendUSBPacket(0, b) | ||||
| 			} | ||||
| 
 | ||||
| 		case usb_IMANUFACTURER: | ||||
| 			b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER) | ||||
| 			if setup.wLength == 2 { | ||||
| 				sendUSBPacket(0, b[:2]) | ||||
| 			} else { | ||||
| 				sendUSBPacket(0, b) | ||||
| 			} | ||||
| 
 | ||||
| 		case usb_ISERIAL: | ||||
| 			// TODO: allow returning a product serial number | ||||
| 			nrf.USBD.TASKS_EP0STATUS.Set(1) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// do not know how to handle this message, so return zero | ||||
| 	nrf.USBD.TASKS_EP0STATUS.Set(1) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // sendConfiguration creates and sends the configuration packet to the host. | ||||
| func sendConfiguration(setup usbSetup) { | ||||
| 	if setup.wLength == 9 { | ||||
| 		sz := uint16(configDescriptorSize + cdcSize) | ||||
| 		config := NewConfigDescriptor(sz, 2) | ||||
| 
 | ||||
| 		sendUSBPacket(0, config.Bytes()) | ||||
| 	} else { | ||||
| 		iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) | ||||
| 
 | ||||
| 		cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) | ||||
| 
 | ||||
| 		header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF) | ||||
| 
 | ||||
| 		controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6) | ||||
| 
 | ||||
| 		functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE) | ||||
| 
 | ||||
| 		callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1) | ||||
| 
 | ||||
| 		cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10) | ||||
| 
 | ||||
| 		dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0) | ||||
| 
 | ||||
| 		out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) | ||||
| 
 | ||||
| 		in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) | ||||
| 
 | ||||
| 		cdc := NewCDCDescriptor(iad, | ||||
| 			cif, | ||||
| 			header, | ||||
| 			controlManagement, | ||||
| 			functionalDescriptor, | ||||
| 			callManagement, | ||||
| 			cifin, | ||||
| 			dif, | ||||
| 			out, | ||||
| 			in) | ||||
| 
 | ||||
| 		sz := uint16(configDescriptorSize + cdcSize) | ||||
| 		config := NewConfigDescriptor(sz, 2) | ||||
| 
 | ||||
| 		buf := make([]byte, 0) | ||||
| 		buf = append(buf, config.Bytes()...) | ||||
| 		buf = append(buf, cdc.Bytes()...) | ||||
| 		sendUSBPacket(0, buf) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (usbcdc USBCDC) handleEndpoint(ep uint32) { | ||||
| 	// get data | ||||
| 	count := int(nrf.USBD.EPOUT[ep].AMOUNT.Get()) | ||||
|  | @ -517,6 +413,10 @@ func (usbcdc USBCDC) handleEndpoint(ep uint32) { | |||
| 	nrf.USBD.SIZE.EPOUT[ep].Set(0) | ||||
| } | ||||
| 
 | ||||
| func sendZlp() { | ||||
| 	nrf.USBD.TASKS_EP0STATUS.Set(1) | ||||
| } | ||||
| 
 | ||||
| func sendViaEPIn(ep uint32, ptr *byte, count int) { | ||||
| 	nrf.USBD.EPIN[ep].PTR.Set( | ||||
| 		uint32(uintptr(unsafe.Pointer(ptr))), | ||||
|  |  | |||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Ron Evans
						Ron Evans