@@ -20,15 +20,16 @@ pub const StructFieldAttributes = struct {
2020 default_value_ptr : ? * const anyopaque = null ,
2121};
2222
23- /// Meant to make transition to zig 0.16 easier
23+ /// Helper to create a struct, wrapping around @Type, meant to make transition to zig 0.16 easier
2424pub fn Struct (
25- comptime layout : std.builtin.Type.ContainerLayout ,
26- comptime BackingInt : ? type ,
27- comptime field_names : []const [:0 ]const u8 ,
28- comptime field_types : * const [field_names .len ]type ,
29- comptime field_attrs : * const [field_names .len ]StructFieldAttributes ,
25+ layout : std.builtin.Type.ContainerLayout ,
26+ BackingInt : ? type ,
27+ field_names : []const [:0 ]const u8 ,
28+ field_types : * const [field_names .len ]type ,
29+ field_attrs : * const [field_names .len ]StructFieldAttributes ,
3030) type {
31- comptime var fields : []const std.builtin.Type.StructField = &.{};
31+ var fields : []const std.builtin.Type.StructField = &.{};
32+ // Iterate over the names, field types, and attributes, creating a new struct field entry
3233 for (field_names , field_types , field_attrs ) | n , T , a | {
3334 fields = fields ++ &[1 ]std.builtin.Type.StructField {.{
3435 .name = n ,
@@ -47,6 +48,7 @@ pub fn Struct(
4748 } });
4849}
4950
51+ // What does this do? It lets you iterate through interfaces and endpoints?
5052pub const DescriptorAllocator = struct {
5153 next_ep_num : [2 ]u8 ,
5254 next_itf_num : u8 ,
@@ -96,6 +98,7 @@ pub const DescriptorAllocator = struct {
9698 }
9799};
98100
101+ /// Wraps a Descriptor type. Returned by the `create` method of the Descriptor.
99102pub fn DescriptorCreateResult (Descriptor : type ) type {
100103 return struct {
101104 descriptor : Descriptor ,
@@ -108,7 +111,7 @@ pub fn DescriptorCreateResult(Descriptor: type) type {
108111}
109112
110113/// USB Device interface
111- /// Any device implementation used with DeviceController must implement those functions
114+ /// Any device implementation used with DeviceController must implement these functions
112115pub const DeviceInterface = struct {
113116 pub const VTable = struct {
114117 ep_writev : * const fn (* DeviceInterface , types.Endpoint.Num , []const []const u8 ) types.Len ,
@@ -191,16 +194,24 @@ pub const Config = struct {
191194 max_current_ma : u9 ,
192195 Drivers : type ,
193196
197+ /// Generate A struct with a field for each field in Drivers, where the type is the third
198+ /// arg of the Drivers' Descriptor's 'create' method.
194199 pub fn Args (self : @This ()) type {
195200 const fields = @typeInfo (self .Drivers ).@"struct" .fields ;
196201 var field_names : [fields .len ][:0 ]const u8 = undefined ;
197202 var field_types : [fields .len ]type = undefined ;
198203 for (fields , 0.. ) | fld , i | {
204+ // Collect field names
199205 field_names [i ] = fld .name ;
206+ // Collect the type info for the Descriptor.create function parameter
200207 const params = @typeInfo (@TypeOf (fld .type .Descriptor .create )).@"fn" .params ;
208+ // Ensure it takes 3 parameters
201209 assert (params .len == 3 );
210+ // The first must be a DescriptorAllocator
202211 assert (params [0 ].type == * DescriptorAllocator );
212+ // The second is usb.types.Len
203213 assert (params [1 ].type == types .Len );
214+ // And save the type of the third
204215 field_types [i ] = params [2 ].type .? ;
205216 }
206217 return Struct (.auto , null , & field_names , & field_types , &@splat (.{}));
@@ -251,11 +262,14 @@ pub fn validate_controller(T: type) void {
251262
252263/// USB device controller
253264///
254- /// This code handles usb enumeration and configuration and routes packets to drivers.
265+ /// Responds to host requests and dispatches to the appropriate drivers.
266+ /// When this type is build (at comptime), it builds descriptor and handler tables based on the
267+ /// provided config.
255268pub fn DeviceController (config : Config , driver_args : config .DriverArgs ()) type {
256269 std .debug .assert (config .configurations .len == 1 );
257270
258271 return struct {
272+ // We only support one configuration
259273 const config0 = config .configurations [0 ];
260274 const driver_fields = @typeInfo (config0 .Drivers ).@"struct" .fields ;
261275 const DriverEnum = std .meta .FieldEnum (config0 .Drivers );
@@ -298,24 +312,33 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type {
298312 var driver_alloc_attrs : []const StructFieldAttributes = &.{};
299313
300314 for (driver_fields , 0.. ) | drv , drv_id | {
315+ // Get descriptor type for the current driver
301316 const Descriptors = drv .type .Descriptor ;
317+ // Call the create method on the descriptor, which wraps it with the allow stuff.
302318 const result = Descriptors .create (& alloc , max_psize , @field (driver_args [0 ], drv .name ));
319+ // Get the descriptor instance from the result.
303320 const descriptors = result .descriptor ;
304321
322+ // If the driver requests memory, then collect the names, types, and attrs
305323 if (result .alloc_bytes ) | len | {
306- driver_alloc_names = driver_alloc_names ++ &[1 ][:0 ]const u8 {drv .name };
307- driver_alloc_types = driver_alloc_types ++ &[1 ]type {[len ]u8 };
308- driver_alloc_attrs = driver_alloc_attrs ++ &[1 ]StructFieldAttributes {.{ .@"align" = result .alloc_align }};
324+ driver_alloc_names = driver_alloc_names ++ &[_ ][:0 ]const u8 {drv .name };
325+ driver_alloc_types = driver_alloc_types ++ &[_ ]type {[len ]u8 };
326+ driver_alloc_attrs = driver_alloc_attrs ++ &[_ ]StructFieldAttributes {.{ .@"align" = result .alloc_align }};
309327 } else {
310328 assert (result .alloc_align == null );
311329 }
312330
313331 assert (@alignOf (Descriptors ) == 1 );
314332 size += @sizeOf (Descriptors );
315333
334+ // Collect handler types, names, and drivers, to later be bound to the appropriate
335+ // endpoints
316336 for (@typeInfo (Descriptors ).@"struct" .fields , 0.. ) | fld , desc_num | {
317337 const desc = @field (descriptors , fld .name );
318338
339+ // Determine which interface numbers this driver owns. If it is an
340+ // InterfaceAssociation, then use the interface count. If it is an Interface,
341+ // then the driver owns just that one interface.
319342 if (desc_num == 0 ) {
320343 const itf_start , const itf_count = switch (fld .type ) {
321344 descriptor .InterfaceAssociation = > .{ desc .first_interface , desc .interface_count },
@@ -329,10 +352,11 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type {
329352 };
330353 if (itf_start != itf_handlers .len )
331354 @compileError ("interface numbering mismatch" );
332- itf_handlers = itf_handlers ++ &[1 ]DriverEnum {@field (DriverEnum , drv .name )} ** itf_count ;
355+ itf_handlers = itf_handlers ++ &[_ ]DriverEnum {@field (DriverEnum , drv .name )} ** itf_count ;
333356 }
334357
335358 switch (fld .type ) {
359+ // Register handler for endpoints
336360 descriptor .Endpoint = > {
337361 const ep_dir = @intFromEnum (desc .endpoint .dir );
338362 const ep_num = @intFromEnum (desc .endpoint .num );
@@ -347,6 +371,7 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type {
347371 ep_handler_drivers [ep_dir ][ep_num ] = drv_id ;
348372 ep_handler_names [ep_dir ][ep_num ] = fld .name ;
349373 },
374+ // Interface association must be first
350375 descriptor .InterfaceAssociation = > assert (desc_num == 0 ),
351376 else = > {},
352377 }
@@ -356,9 +381,12 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type {
356381 field_attrs [drv_id ] = .{ .default_value_ptr = & descriptors };
357382 }
358383
384+ // Finally, bind the handler functions based on the data collected above.
359385 const Tuple = std .meta .Tuple ;
386+ // Create a tuple with the appropriate types
360387 const ep_handlers_types : [2 ]type = .{ Tuple (& ep_handler_types [0 ]), Tuple (& ep_handler_types [1 ]) };
361388 var ep_handlers : Tuple (& ep_handlers_types ) = undefined ;
389+ // Iterate over all IN and OUT endpoints and bind the handler for any that are set.
362390 for (& ep_handler_types , & ep_handler_names , & ep_handler_drivers , 0.. ) | htypes , hnames , hdrivers , dir | {
363391 for (& htypes , & hnames , & hdrivers , 0.. ) | T , name , drv_id , ep | {
364392 if (T != void )
@@ -558,6 +586,7 @@ pub fn DeviceController(config: Config, driver_args: config.DriverArgs()) type {
558586 }
559587 }
560588
589+ // Return the appropriate descriptor type as determined by the top 8 bits of the value.
561590 fn get_descriptor (value : u16 ) ? []const u8 {
562591 const asBytes = std .mem .asBytes ;
563592 const desc_type : descriptor.Type = @enumFromInt (value >> 8 );
0 commit comments