 My name is Johan Fischer. I'm the engineer for Nordic Semiconductor and USB support maintainer for Z5 project. Yeah, so the title is a bit weird, maybe because I'm maintainer, so I'm not sure I can provide you a perspective from the application or from the users, but I know some pitfalls, and I tried to look for some questions in the Discord or internal channels, and yeah, what the user have for difficulties to configure to get some parts working, so I will try to provide some guidelines for this. We updated documentation recently, so it's, I think it's a bit better, but there's still some gaps, and I also used preparation for this talk to improve the condition, but I still working in it, so let's start. So I will just show how to enable USB support, what can I configure USB support in ZFAR, and then I will go over the supported classes in the tree and points on how to configure some pitfalls and stuff, and yeah, let's start. So how to enable USB device support in ZFAR? First thing you need is to, from your board, perspective to, from board device trees, to provide ZFAR UBC0 node labeling. That is node labeling used internally by the stack to identify a controller. What one is, in that case, is USB-D for Nordic swim conductor, but it differs from the board, yeah. And for the current use, we have, maybe no, we have two device stacks now in the ZFAR, the current one and the new experiment on the front floor. This example is for the current one and most part configured in using cat config options, yeah. So you have to enable device stack and set vendor IDs and product IDs values, and then also device, the strings configuration is done using cat configs, and it speaks, yeah, you can change in the runtime. As for the configuration, self-powered or maximum power is for the specific configuration, only one configuration is supported for the current stack is also using cat config options, so you can change it at the runtime, actually, and that's one of the issues, but yeah. And you need a small code to, that actually depends on the classes you use, or your application, but you need to provide some minimal code to enable USB. And one thing not everyone knows, there's a, you can pass a status code to USB enable function, and it will be code every time there is a new event on the low level, yeah, it's actually as it is, it defines up on the driver level and on the stack, and that can be used to let the application know if the device, if the host selected a configuration, so you can prepare your application that the next time the host will start communication, yeah, it doesn't, it needs to be the case, yeah, but it's like the first step, yeah, I know something happened, yeah, and yeah, you can also check for the results, yeah, and so there are a few other cat config options, they are maybe weird, or yeah, it's, the reason isn't that's how the current stack was developed over the years, yeah, and function are added or simplified, and there's a weird cat config options, that configues the composite device, so in the current state of industry, yeah, this function just changes the code triple, yeah, for device plus device subclass on device protocol, so if it's this option is not set, so in device descriptor the code triple is set to zero, which means that the host has to look at the interface descriptor, which function, and look for the, for the specific function, like if there's yet, if there's mass storage class enabled, the host will look at the interface descriptor of the, of that specific interface descriptor and identify the function, yeah, here in the example it's a mass storage class, and so you as application or as user doesn't have to enable this function if you use, for example, even if you use multiple instances of less, in the new stack as possible for mass storage class, yeah, or the reason, the only reason to enable this is if you class is, has multiple interfaces, like for example, CDC-SM, CDC-SM actually selects this option, but like for example, CDC-SM, if you use CDC-SM you have to enable this option, for the reason is that this option changes the code triple in the device descriptor to this specific value is, and that advice the host to use interface association descriptor code triple to identify what interfaces belong to one function, so the host, like for the CDC-SM, there are two interfaces and the host needs to identify what interfaces belong to a function, so if you use CDC-SM, ECM class please enable this option so that the host, windows or linux as a matter can identify the interfaces belong to a specific function, and as we have a USB device in slice at both, at both, so that is specific for the best, both like USB dongles in F50 to 840 dongles for similar devices, and the users would like to, to have kind of run to run the USB support at both to use CDC-SM for logging, that's the only reason for this option, and you can also use it with the snippet with CDC-SM snippet to enable logging just at the run time from the beginning, you don't have to call USB enable from your application in that case, but if that application uses some USB classes, you have a conflict, yeah. There's other support for binary object storage descriptors, which is enabled by KACONVIC USB device was option, and it actually it enables, what it does, it enables the OS handling by the stack and allows the user to register, for example, a compliance, a compatibility OS descriptor to a root OS descriptor, but the thing is that this option changes the BCD USB value creator to a two-tane, like it's not, to signalize the host, please look for the OS descriptor, for example, for 8 p.m. If you control a support at 8 p.m., you can use OS to provide the host information, yeah. And this also KACONVIC USB device OS descriptor support, the option to enable that, it's mainly used, or actually in the tree used only by R&Ds class, and that is to provide Windows OS descriptors for the host, yeah. In the, that should be actually covered now in the current documentation for USB device support, so. And now we have a new device support in the tree for alpha editing, and there are a few differences, that is still experimentable, you can use it for a few user cases, but it's, yeah. So differences that we don't have that many KACONVIC options now, so it's just one enabled device stack next, yeah. And everything to configure, like PAD and vendor ID, needs to be done by the application, yeah, that's the difference, so. And the reason for that is that you can disable your USB device and reconfigure when the idea of the productivity on restarted, yeah. Also change other properties from USB device descriptor and ISO class registration, you can remove, for example, you have CDC-SM instance, you can remove shutdown, remove CDC-SM, register another class and power up again the USB device. That's more flexible if you compare that with the current stack. I will explain what classes are supported or not with for the new experimental device stack, so let's start with CDC-SM, that's one, maybe many people complain if they start working with, how to use CDC-SM for logging or for shell or for application specifics, I think it's that you are for, our driver API in Zephyrus is used by various subsistence for communication that's like for Bluetooth, you can attach HCI transport layer through the UART interface and there's a thread, that's named an NPC support that also uses API. And API itself, there's another thing that, also maybe confusing for new people that we have three types of UART API, it's a simple one, it's polling, then interrupt driven in testing and not every driver support testing, for example, but we have subsistence that uses testing for default but for back for polling, for example. So that's, and it's not actually not a driver property or it's just an implementation API. So CDC-SM implementation provides a virtual UART interface, it doesn't use a real hardware, it's an emulated interface and it's desirable for emulation to behave like a real interface, it's not always possible. Well, people have different expectations and CDC-SM limitation supports pollicant interrupt driven APIs only not testing. And there's actually no easy way to, never is but if you start a developer application you don't know what API, what UART driver supports what API, I have to look at the code or try it out and so. And how it looks, it's the same picture yesterday, but they have on the bottom there's USB connection between the controllers, that it's actual connection and the top is serial connection. So your application on the bot side, on the remote, on the ZIFI application, the interface is UART API, that we have there on logical level there's only serial connection, you can use only that, but it's UART API provides and the ZIFI side. The compatibility for the CSEM is ZIFI, CDC-SM UART, it will stay as in, it will not change in the new device stack, yeah? So if you switch to new device stack as default, this class will not read that much. It will just stay the same interface here because it's the common one from the UART. Yeah, and to instead it, UART, virtual UART for your application, you just need to provide a node and compatibility and you can have approximately three virtual devices on your board, yeah? So if, yeah, but it depends, for example, if you controller supports six in endpoints, yeah, you can have three virtual devices because you need for each device, you need two in endpoints, one block, one interrupt, yeah? Yeah, and finally you have to enable serial support in the car config option. So if your application for some level, if you don't need logging anymore in production, yeah, you can just disable CRL and that's for real driver. There's no difference, it's the same insertization level, yeah, same car config option to enable or disable from configuration point of view, it's like really UART controller. And the one thing there is in application you have, what you can do is to, after you enable USB, or before you start using UART, this virtual UART controller, you can wait for a DTL redi signal, yeah? That's the only way to determine if an application on the whole side start communication, or open the port or the interface, there is no other ways, yeah? Maybe you can, if, what, for example, Linux was though, it changed about it. We could have, there's a hacked interface to detect that, but I certainly don't like it and we will work another interface notification system to signal that, but our UART API doesn't prove right away or that polling, yeah? What you can do is just to poll for this that redi signal, I think it is. I think is you can even use a call mix that device is configured because that means that hosts recognize your device and select it to configuration, but it doesn't mean there is an application that actively use the interface, yeah? So then for you, if you write a custom application specific to CDC-SM UART, yeah? The only way to know if there's some application using it or not is to wait for the signal and for the application to use the signal on the host, actually, yeah, what was I saying? The thing is that as a communication for the CDC-SM UART is completely, as heavily used, the communication is determined by the host, yeah? If there's no application on the host side, there will be no in-out token. And for example, if you application actively writes to UART, yeah, start to write, you will lose the data, like on real UART, yeah? On it will just block and some moment not block, but not try I use anymore on virtual UART, yeah? So that's the thing, and if there's a behavior like that if the data passed to UART on UART 3.4.3 and device is not configured, it will be discarded, yeah? It's just not to slow down application at the startup, but the difference is in configurable state if UART pull in is that it discussed the character from the tail, so it's just like overflow and drop the first one, yeah? The difference to the Q that you will not have is actually if you design the application for the UART API, but not specific for the CDCSM UART, that should just work, yeah? So if you start some custom application, don't try to think like of CDCSM specific, yeah? Write it like for the UART, yeah, for real driver, yeah, and that should work. I hope so, if not blame me. Yeah, it's a mass storage class. It's another one that it's some kind of difficult to understand how to configure it, yeah? But we have implementation for the current and new USB device support in the tree, and there are two car config option to enable this support. It's only car config option is used for mass storage class support. So I have no device tree is needed because it's just a thin layer in the USB, yeah, this year, like USB code, SCSI code, and finally the backend that is used as for block devices, yeah? And so the new implementation allows you to have multiple LAN instances, yeah, if you have two stickers or two flash disk or whatever, yeah? And but both implementations use a disk access subsystem as backend, yeah, for the block devices, yeah? So that is the overview of this, yeah? On the top is mass storage class and it uses disk access API. And each driver in the API, if this is enabled, yeah, it's a node in the double linked list, yeah? So it's always, yeah? That is, you can pass the argument. Internally, yeah, you pass the argument to disk access API with the name of a disk and it will go to the double linked list and select the one and use it for write, read or whatever access, yeah? And, yeah, the only car config option you have to use to select what of this disk or drivers should be used in for the current USB stack is car config mass storage disk name. And new implementation is a bit different as an instant sentient macro for the logical units and then you can pass disk name. So the thing is that current implementation supports only one disk. You can have only one disk exposed to the host, RAM disk flash or SDE MMC. New implementation allows you to expose multiple disks but there are limitations on the backend. The thing is that RAM disk can be configured is configured using car config. So you can have only one instance of the RAM disk. It can switch to use device tree for the configuration but it's a bit tricky so that needs more discussion but that would, for testing is the very nicest. You have trouble with mass storage class port use RAM disk as backend. It should always work, yeah? Because it just used something in the... Some area is in the memory. It's actually defined in the disk called selfie and it's like always works here. If that doesn't work open a bug report for USB. And then we have a flash disk support. So this one supports multiple instances and can be configured using device tree. Just to provide a flash disk and disk name property and you have multiple instances of flash disk. And by flash I mean row nor flash like on the SOC or on external flash. And finally SDE MMC, you can use it with a spy driver or some specific controller but usually here with SDE MMC you can even with new support you can use multiple instances because there's one option in CACONFIG and that is the name, volume name, yeah? And because the mass storage class or disk access uses names to identify the disk, yeah? You can have more than one, yeah? So it's one of the issues. So we have to fix this part and probably discuss how to handle RAM disk and so on. And there are a few examples, yeah? That is for the block device on a flash partition. Yeah, you have actually to describe your partition cell or if you have already defined one on the board tree you can, you should delete it but be careful, yeah? If you enable this portion here to be exposed to the host make sure that it's not used by other subsystem like this one, I don't remember the name for the setting subsystem, whatever, yeah? This is one of the things in CACONFIG stack. People do example configure, some example configuration combined with another one and then doesn't work and it's crashed on the board because this partition is used by some other subsystem and you have to delete it before you instate it knowing here and yeah, it's for newcomer, it's actually a mess to get to identify why it doesn't work, yeah, why my firmware crashes because I won't try to access the same partition and main folder or something like this. And finally here you can describe the disk, the flash disk itself and the most weird thing here is a NAND, you have to name it NAND but it's not NAND, it is NOR, still NOR on throw flash but the NAND is used or you can have to use NAND if you want to allow, you film the access this partition to the FAT file system because FAT file system uses NAND to identify this flash disk. So it's not, be not confused, yeah? It's not converted to NAND, yeah? It's still the same NOR flash but that is how it is in the tree, it's not only in USB that it's other in other areas for the file system and so on. And you have to provide the same name here, yeah, not here, that's wrong here, just ignore it, you don't have to, that's using device tree for the flash, that's a typo. So and another example is to using is the MMC, that is very magic, yeah? Because you don't, here on the car config side, you just configures to USB on the Enable Smart Storage class but you don't have to, in the current state of three, you don't need to enable anything in car config so just drivers magically enable just by compatibility here. So that's a kind of issue we had, maybe we have to fix that somehow, but yeah, the thing is like, if you look what kind of car config option I have to enable and enables that because it's there, yeah? But it's enabled if that's fine, this compatibility but for the user, it's weird because I see the car config option, everything happens because it's, the node is still not there, or they cannot enable that somehow in the config file and so on. So the thing is that everything comes here, you have to describe your controller on then this like MMC and here node inside the controller to enable two drivers, yeah? And that's, I think that it's for the user, at least we had that last time this issue on the GitHub but that just was kind of, yeah, problematic to explain why it's there, so. Then Bluetooth host controller interface, that works actually, very nice with Sapphire, we have support for Bluetooth low energy controller and, but there is no support for the classic EDI-ECO channels, yeah? We don't support that and what this transport there does, it uses host controller interface role API to expose host controller interface to remote, for example to link source or I don't know what else works with that one. Yeah, and we have two implementations for the current new USB device support and this for the current implementation there's a limitation or as an issue that it's kind of combined with other classes. So you device, if you use that with the current stake your device has to support only one function, yeah? And only the host controller interface transport layer do not combine it with CDC-SM or with VU, it will not work because of how it was designed, yeah? We don't support this type of transfer with what low energy link layer only, so this part in the driver implement or in the class implementation was just skipped, yeah, it's not there and what happens if you look it in with multiple interfaces, yeah? And for example to the link source it tries to claim this interface too, yeah? And if that is CDC-SM, you can access that anymore, yeah? That's the issue, yeah? So you have for the, with the current stake you have provide just single function device not combined with CDC-SM or the VU whatever, yeah, it will not work. Even with so much fixed provider fixed to the VT-USB driver, but that was about interface number so it's, this issue is still there, but that is fixed in the new implementation, you can combine it with CDC-SM or other classes, but there's still no functionality, it just consumes resources on the controller side because we don't, in Bluetooth we don't have this type of synchronous data support, yeah? It's not there. So even with new stake if you combine it, it just wasted some, it would waste isocronos endpoint resources, yeah? But that is, yeah, we have to refit it somehow. So we have networking support by, provided by CDC-SM, EM and NG support, that works mostly the same, yeah? It provides a virtual internet connection between remote and ZFI network support. So it doesn't expose you, you internet controller to the host, yeah? It creates actually a virtual internet connection between the interface on the firmware on the host, yeah? And that's the reason we have to provide two make addresses for this implementation. The one is, for example, like ECM is I make address, that will be used by the host, yeah? On the host side, the interface controller, we have this I make address, but because there's a kind of provided internet, virtual internet connection, we also have local make address. It's the same for all three implementations, yeah? But the way how to provide this information to the host is a bit different, yeah? We have a new implementation on ECM support, it's improved a bit, but maybe we can also work on some solution to export real internet controller, yeah? To the host for whatever reason, yeah? But people are creative, we'll find some excuse, yeah? For testing, I don't know. So the configuration for CDCCM is for the current implementation is that these make addresses are hardcoded and you cannot have multiple instances of the cluster, it's just always on. There's a remote address is hardcoded, remote address can be set using a carton reduction, but local address is hardcoded and there is no implementation to use EPI from network management to change this make address, yeah, it's a mess, yeah, it's an issue, but, I didn't hear people complain about that, but I look at it for the documentation and for the internet founder that's a bit, yeah, it's not nice. The same for CDC, that ties the typo, and new ECM supports, you can set the make addresses using device tree, both, remote and the local one. If you do not provide local make address, it will be a random one, but there is also the EPI implemented to set it from the shell, you can change the local make address from the shell, yeah. And finally, CDCM and NDS for the current implementation has the same issues, but there's even the local make is hardcoded, yeah. And if you use NDS, please enable carton-fig device or S descriptor, I will, it's otherwise window source will not recognize the device or not the proper driver, yeah. Yeah, HID, yeah, another thing that they have, they have implementation for, as a new, there's only one, yeah, in the tree. I'm currently working on a new one, and HID supports multiple instances, yeah. But it abuses device driver model, yeah. So there's no HID device EPI as such, yeah. There's no device config or device data provided internally. So it just uses this device model EPI to get the instance, yeah, nothing more. And installation itself is provided using listify macro and carton-fig option device count, yeah. There's a carton-fig template, and if you select two HID devices, listify macro will create two instances internally. And in your application, there we explain. So in your application, you can get it based on the HID prefiscundant number postfix, yeah. So for HID, each instance required HID report descriptor. That's on the, right, sorry. So that looks the same. You could use the same descriptor for Bluetooth HID, yeah. It's in EPI is split into parts where as for HID, we have two headers, one is common one that you can also use for Bluetooth HID. And API part for device support, yeah. And yeah, in the simplest case, you just have to provide a one callback. There's an interface to register, yeah. And you just need to provide interrupt in because interrupt in endpoint is required for HID. Yeah, you have to provide just the one for the, to get it working, yeah. In simplest possible way, just a single callback that just write the endpoint and increments here in the report. The report here is just two octets, that's ID and some counting number. And yeah, that's very small example for the application, yeah. And here you have to use status callback. And if the device is configured, if you get the event, you can just ping the callback one time to get the communication started. And yeah, the host will obtain the reports based on the descriptor settings, yeah. There's a default descriptor settings by the Cloud Compute options in the communication will not get in details here. But the thing is that now you here in, it is in set a device, an application, you have to use device binding but it's problematic anyway. And I know people would like to remove that. And the thing is that you, what is confusing is that you have to register a device. Yeah, you have to, you get a device, but then you have to register a device. But it's not device, it's just a interface, yeah, provided by heat ops, yeah. And yeah, it's used by the core. So it's a bit confusing. And there was a progress to move to device three to instead of using device three, but it's problematic as well because the resources here, yeah, it's on the controller side, yeah, like end points, but we are on the opposite side on the user part, so. And one of the issues is that with current interpretation that other config options applies to all instances, yeah. If you change the polling interval, it applies to all instances, yeah, that's a big issue. Or if you enable output, out interrupt end point, it applies to all instances, yeah. So it's a mess, but as long as you, if you implement two keyboards, fine, or the keyboard mouse, that should work. Audio class, I will skip that. If you, yeah, as well, so, questions. Yeah. Yeah. Seems to be working. Two quick questions, one comment. Yeah. I see the move of configuration settings towards the application side. Yeah. In the new version. Is there a way for the application side to inquire or handle situation when the number of end points provided by a device is exceeded or it's not available? So how, then, the question of the application handles this exception condition when the number of end points gets error on initialization. But that happens at runtime. Yeah. So when you design the software for a particular purpose and you don't necessarily target single device, how would you handle the least common denominator or handle errors or design the application to run without it? There is no easy way, then, to use, to get information about your controller, how many end points it supports and to know how we, sure, we can improve implementation, class documentation sector to document how many end points it requires. But the thing is, if you design a specific application, you have to know your controller and what it supports and then select your configuration. It feeds the purpose of an operating system abstracting hardware resources that you want to not be specifically tied to one particular hardware. But I understand your point. Thank you. The thing is, in the tree, we have various of boards and, like, for example, if you look alone at STM, how many controller, different configuration of controllers like, yeah, and it's all, it's the issue, yeah, that sometimes it doesn't work if people select, I don't know, three CDC STM instances and on HID, no, you have just four interrupt end points. For example, in end points, two of them are like two interrupts and you're out of the resources, that's, yeah. But you will, in the new support, it's there will be detailed error message that's just gonna configure, apply this configuration, but it's on runtime, yeah. You can, because we, there was a, people wanted to have that, this functionality, yeah. Just to do, maybe crazy things, but just reconfigure behavior of USB device at runtime. Change configuration to a new one. It's also for us, it's very good for testing, yeah. We have child support, we can change device configuration at runtime once we start it, yeah. It's CDCM, you restart it as ECM and so on. The same spirit, how about setting up the interrupt priority when working with a specific, or configuring specific USB controller? I don't get it, so. As part of the configuration of the specific USB controller to work as a device, would you not be able to configure the interrupt priority of the USB IP for it to be, yeah, but that's a different setting for the driver and for the subsystem. So the driver is, so you're setting the application still doesn't have control over the ability to, over the specific hierarchy priority? No. It's the, it's the config option. And actually it should be device three, property. Yeah, it's device three. I can't configure it on the device three. All right, got the message, thank you. No comments. It's just that the, we can discuss on the floor. No, I understand. It's just the use of new may be confusing in some amount of time. So if you use a V2, it would be more clear. Thanks. Okay. Carlos, come on. All right. Okay, sorry. No time, no time. Okay, thank you.