2727#include "nxos/drivers/aic.h"
2828#include "nxos/util.h"
2929
30+ #include "usb_ch9.h"
31+
3032/* The USB controller supports up to 4 endpoints. */
3133#define PBDRV_USB_NXT_N_ENDPOINTS 4
3234
9698 * don't have a vendor ID to use. Therefore, we are currently
9799 * piggybacking on Lego's device space, using an unused product ID.
98100 */
99- static const uint8_t pbdrv_usb_nxt_device_descriptor [] = {
100- 18 , USB_DESC_TYPE_DEVICE , /* Packet size and type. */
101- 0x10 , 0x02 , /* This packet is USB 2.1 (needed for BOS descriptors). */
102- PBIO_PYBRICKS_USB_DEVICE_CLASS , /* Class code. */
103- PBIO_PYBRICKS_USB_DEVICE_SUBCLASS , /* Sub class code. */
104- PBIO_PYBRICKS_USB_DEVICE_PROTOCOL , /* Device protocol. */
105- MAX_EP0_SIZE , /* Maximum packet size for EP0 (control endpoint). */
106- 0x94 , 0x06 , /* Vendor ID : LEGO */
107- 0x02 , 0x00 , /* Product ID : NXT */
108- 0x00 , 0x02 , /* Product revision: 2.0.0. */
109- 1 , /* Index of the vendor string. */
110- 2 , /* Index of the product string. */
111- 0 , /* Index of the serial number (none for us). */
112- 1 , /* The number of possible configurations. */
101+ static const pbdrv_usb_dev_desc_t pbdrv_usb_nxt_device_descriptor = {
102+ .bLength = sizeof (pbdrv_usb_dev_desc_t ),
103+ .bDescriptorType = DESC_TYPE_DEVICE ,
104+ .bcdUSB = 0x0210 , /* This packet is USB 2.1 (needed for BOS descriptors). */
105+ .bDeviceClass = PBIO_PYBRICKS_USB_DEVICE_CLASS ,
106+ .bDeviceSubClass = PBIO_PYBRICKS_USB_DEVICE_SUBCLASS ,
107+ .bDeviceProtocol = PBIO_PYBRICKS_USB_DEVICE_PROTOCOL ,
108+ .bMaxPacketSize0 = MAX_EP0_SIZE ,
109+ .idVendor = 0x0694 , /* Vendor ID : LEGO */
110+ .idProduct = 0x0002 , /* Product ID : NXT */
111+ .bcdDevice = 0x0200 , /* Product revision: 2.0.0. */
112+ .iManufacturer = 1 ,
113+ .iProduct = 2 ,
114+ .iSerialNumber = 0 ,
115+ .bNumConfigurations = 1 ,
113116};
114117
115- static const uint8_t pbdrv_usb_nxt_dev_qualifier_desc [] = {
116- 10 , USB_DESC_TYPE_DEVICE_QUALIFIER , /* Packet size and type. */
117- 0x10 , 0x02 , /* This packet is USB 2.1. */
118- PBIO_PYBRICKS_USB_DEVICE_CLASS , /* Class code */
119- PBIO_PYBRICKS_USB_DEVICE_SUBCLASS , /* Sub class code */
120- PBIO_PYBRICKS_USB_DEVICE_PROTOCOL , /* Device protocol */
121- MAX_EP0_SIZE , /* Maximum packet size for EP0. */
122- 1 , /* The number of possible configurations. */
123- 0 , /* Reserved for future use, must be zero. */
118+ static const pbdrv_usb_dev_qualifier_desc_t pbdrv_usb_nxt_dev_qualifier_desc = {
119+ .bLength = sizeof (pbdrv_usb_dev_qualifier_desc_t ),
120+ .bDescriptorType = DESC_TYPE_DEVICE_QUALIFIER ,
121+ .bcdUSB = 0x0210 , /* This packet is USB 2.1. */
122+ .bDeviceClass = PBIO_PYBRICKS_USB_DEVICE_CLASS ,
123+ .bDeviceSubClass = PBIO_PYBRICKS_USB_DEVICE_SUBCLASS ,
124+ .bDeviceProtocol = PBIO_PYBRICKS_USB_DEVICE_PROTOCOL ,
125+ .bMaxPacketSize0 = MAX_EP0_SIZE ,
126+ .bNumConfigurations = 1 ,
127+ .bReserved = 0 ,
124128};
125129
126130// These enumerations are specific to the configuration of this device.
@@ -181,54 +185,61 @@ static const uint8_t pbdrv_usb_nxt_bos_desc[] = {
181185 0x00 , /* bAltEnumCode = Does not support alternate enumeration */
182186};
183187
184- static const uint8_t pbdrv_usb_nxt_full_config [] = {
185- 0x09 , USB_DESC_TYPE_CONFIG , /* Descriptor size and type. */
186- 0x20 , 0x00 , /* Total length of the configuration, interface
187- * description included.
188- */
189- 1 , /* The number of interfaces declared by this configuration. */
190- 1 , /* The ID for this configuration. */
191- 0 , /* Index of the configuration description string (none). */
192-
193- /* Configuration attributes bitmap. Bit 7 (MSB) must be 1, bit 6 is
194- * 1 because the NXT is self-powered, bit 5 is 0 because the NXT
195- * doesn't support remote wakeup, and bits 0-4 are 0 (reserved).
196- */
197- 0xC0 ,
198- 0 , /* Device power consumption, for non self-powered devices. */
199-
200- /*
201- * This is the descriptor for the interface associated with the
202- * configuration.
203- */
204- 0x09 , USB_DESC_TYPE_INT , /* Descriptor size and type. */
205- 0x00 , /* Interface index. */
206- 0x00 , /* ID for this interface configuration. */
207- 0x02 , /* The number of endpoints defined by this interface
208- * (excluding EP0).
209- */
210- PBIO_PYBRICKS_USB_DEVICE_CLASS , /* Interface class ("Vendor specific"). */
211- PBIO_PYBRICKS_USB_DEVICE_SUBCLASS , /* Interface subclass (see above). */
212- PBIO_PYBRICKS_USB_DEVICE_PROTOCOL , /* Interface protocol (see above). */
213- 0x00 , /* Index of the string descriptor for this interface (none). */
214-
188+ typedef struct PBDRV_PACKED {
189+ pbdrv_usb_conf_desc_t conf_desc ;
190+ pbdrv_usb_iface_desc_t iface_desc ;
191+ pbdrv_usb_ep_desc_t ep_out ;
192+ pbdrv_usb_ep_desc_t ep_in ;
193+ } pbdrv_usb_nxt_conf_t ;
194+
195+ static const pbdrv_usb_nxt_conf_t pbdrv_usb_nxt_full_config = {
196+ .conf_desc = {
197+ .bLength = sizeof (pbdrv_usb_conf_desc_t ),
198+ .bDescriptorType = DESC_TYPE_CONFIGURATION ,
199+ .wTotalLength = sizeof (pbdrv_usb_nxt_conf_t ),
200+ .bNumInterfaces = 1 ,
201+ .bConfigurationValue = 1 ,
202+ .iConfiguration = 0 ,
203+ /* Configuration attributes bitmap. Bit 7 (MSB) must be 1, bit 6 is
204+ * 1 because the NXT is self-powered, bit 5 is 0 because the NXT
205+ * doesn't support remote wakeup, and bits 0-4 are 0 (reserved).
206+ */
207+ .bmAttributes = USB_CONF_DESC_BM_ATTR_MUST_BE_SET | USB_CONF_DESC_BM_ATTR_SELF_POWERED ,
208+ .bMaxPower = 0 ,
209+ },
210+ .iface_desc = {
211+ .bLength = sizeof (pbdrv_usb_iface_desc_t ),
212+ .bDescriptorType = DESC_TYPE_INTERFACE ,
213+ .bInterfaceNumber = 0 ,
214+ .bAlternateSetting = 0 ,
215+ .bNumEndpoints = 2 ,
216+ .bInterfaceClass = PBIO_PYBRICKS_USB_DEVICE_CLASS ,
217+ .bInterfaceSubClass = PBIO_PYBRICKS_USB_DEVICE_SUBCLASS ,
218+ .bInterfaceProtocol = PBIO_PYBRICKS_USB_DEVICE_PROTOCOL ,
219+ .iInterface = 0 ,
220+ },
215221 /*
216222 * Descriptor for EP1.
217223 */
218- 7 , USB_DESC_TYPE_ENDPT , /* Descriptor length and type. */
219- 0x1 , /* Endpoint number. MSB is zero, meaning this is an OUT EP. */
220- 0x2 , /* Endpoint type (bulk). */
221- MAX_RCV_SIZE , 0x00 , /* Maximum packet size (64). */
222- 0 , /* EP maximum NAK rate (device never NAKs). */
223-
224+ .ep_out = {
225+ .bLength = sizeof (pbdrv_usb_ep_desc_t ),
226+ .bDescriptorType = DESC_TYPE_ENDPOINT ,
227+ .bEndpointAddress = 0x01 , /* Endpoint number. MSB is zero, meaning this is an OUT EP. */
228+ .bmAttributes = EP_TYPE_BULK ,
229+ .wMaxPacketSize = MAX_RCV_SIZE ,
230+ .bInterval = 0 ,
231+ },
224232 /*
225233 * Descriptor for EP2.
226234 */
227- 7 , USB_DESC_TYPE_ENDPT , /* Descriptor length and type. */
228- 0x82 , /* Endpoint number. MSB is one, meaning this is an IN EP. */
229- 0x2 , /* Endpoint type (bulk). */
230- MAX_RCV_SIZE , 0x00 , /* Maximum packet size (64). */
231- 0 , /* EP maximum NAK rate (device never NAKs). */
235+ .ep_in = {
236+ .bLength = sizeof (pbdrv_usb_ep_desc_t ),
237+ .bDescriptorType = DESC_TYPE_ENDPOINT ,
238+ .bEndpointAddress = 0x82 , /* Endpoint number. MSB is one, meaning this is an IN EP. */
239+ .bmAttributes = EP_TYPE_BULK ,
240+ .wMaxPacketSize = MAX_SND_SIZE ,
241+ .bInterval = 0 ,
242+ },
232243};
233244
234245static const uint8_t pbdrv_usb_nxt_string_desc [] = {
@@ -625,17 +636,17 @@ static void pbdrv_usb_handle_std_request(pbdrv_usb_nxt_setup_packet_t *packet) {
625636 index = (packet -> value & USB_WVALUE_INDEX );
626637 switch ((packet -> value & USB_WVALUE_TYPE ) >> 8 ) {
627638 case USB_DESC_TYPE_DEVICE : /* Device descriptor */
628- size = pbdrv_usb_nxt_device_descriptor [ 0 ] ;
629- pbdrv_usb_nxt_write_data (0 , pbdrv_usb_nxt_device_descriptor ,
639+ size = pbdrv_usb_nxt_device_descriptor . bLength ;
640+ pbdrv_usb_nxt_write_data (0 , ( const uint8_t * ) & pbdrv_usb_nxt_device_descriptor ,
630641 MIN (size , packet -> length ));
631642 break ;
632643
633644 case USB_DESC_TYPE_CONFIG : /* Configuration descriptor */
634- pbdrv_usb_nxt_write_data (0 , pbdrv_usb_nxt_full_config ,
635- MIN (pbdrv_usb_nxt_full_config [ 2 ] , packet -> length ));
645+ pbdrv_usb_nxt_write_data (0 , ( const uint8_t * ) & pbdrv_usb_nxt_full_config ,
646+ MIN (pbdrv_usb_nxt_full_config . conf_desc . wTotalLength , packet -> length ));
636647
637648 /* TODO: Why? This is not specified in the USB specs. */
638- if (pbdrv_usb_nxt_full_config [ 2 ] < packet -> length ) {
649+ if (pbdrv_usb_nxt_full_config . conf_desc . wTotalLength < packet -> length ) {
639650 pbdrv_usb_nxt_send_null ();
640651 }
641652 break ;
@@ -654,8 +665,8 @@ static void pbdrv_usb_handle_std_request(pbdrv_usb_nxt_setup_packet_t *packet) {
654665 break ;
655666
656667 case USB_DESC_TYPE_DEVICE_QUALIFIER : /* Device qualifier descriptor. */
657- size = pbdrv_usb_nxt_dev_qualifier_desc [ 0 ] ;
658- pbdrv_usb_nxt_write_data (0 , pbdrv_usb_nxt_dev_qualifier_desc ,
668+ size = pbdrv_usb_nxt_dev_qualifier_desc . bLength ;
669+ pbdrv_usb_nxt_write_data (0 , ( const uint8_t * ) & pbdrv_usb_nxt_dev_qualifier_desc ,
659670 MIN (size , packet -> length ));
660671 break ;
661672
0 commit comments