{"action":"created","issue":{"url":"https://api.github.com/repos/arduino/Arduino/issues/3304","labels_url":"https://api.github.com/repos/arduino/Arduino/issues/3304/labels{/name}","comments_url":"https://api.github.com/repos/arduino/Arduino/issues/3304/comments","events_url":"https://api.github.com/repos/arduino/Arduino/issues/3304/events","html_url":"https://github.com/arduino/Arduino/pull/3304","id":86241541,"number":3304,"title":"[RFC] Pluggable USB core for AVR","user":{"login":"facchinm","id":8843437,"avatar_url":"https://avatars.githubusercontent.com/u/8843437?v=3","gravatar_id":"","url":"https://api.github.com/users/facchinm","html_url":"https://github.com/facchinm","followers_url":"https://api.github.com/users/facchinm/followers","following_url":"https://api.github.com/users/facchinm/following{/other_user}","gists_url":"https://api.github.com/users/facchinm/gists{/gist_id}","starred_url":"https://api.github.com/users/facchinm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facchinm/subscriptions","organizations_url":"https://api.github.com/users/facchinm/orgs","repos_url":"https://api.github.com/users/facchinm/repos","events_url":"https://api.github.com/users/facchinm/events{/privacy}","received_events_url":"https://api.github.com/users/facchinm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"facchinm","id":8843437,"avatar_url":"https://avatars.githubusercontent.com/u/8843437?v=3","gravatar_id":"","url":"https://api.github.com/users/facchinm","html_url":"https://github.com/facchinm","followers_url":"https://api.github.com/users/facchinm/followers","following_url":"https://api.github.com/users/facchinm/following{/other_user}","gists_url":"https://api.github.com/users/facchinm/gists{/gist_id}","starred_url":"https://api.github.com/users/facchinm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facchinm/subscriptions","organizations_url":"https://api.github.com/users/facchinm/orgs","repos_url":"https://api.github.com/users/facchinm/repos","events_url":"https://api.github.com/users/facchinm/events{/privacy}","received_events_url":"https://api.github.com/users/facchinm/received_events","type":"User","site_admin":false},"milestone":null,"comments":12,"created_at":"2015-06-08T16:19:18Z","updated_at":"2015-06-23T09:04:15Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/arduino/Arduino/pulls/3304","html_url":"https://github.com/arduino/Arduino/pull/3304","diff_url":"https://github.com/arduino/Arduino/pull/3304.diff","patch_url":"https://github.com/arduino/Arduino/pull/3304.patch"},"body":"This PR introduces the concept of Pluggable USB modules to help getting the best from our tiny ATmega32u4 without overhauling the core library with functions that could be useful for no more than 10% of the users.\r\n\r\nUsing this method we can _plug_ a library using the USB core by simply including its header in the sketch, and if not used it will not occupy additional resources.\r\n\r\nIt is of course a work in progress (thus tagged as RFC), still not ported to DUE core, and VERY probably bug-prone. Also, the memory footprint is not minimized.\r\n\r\n_Useful infos_\r\n* the CDC module is now non-removable (only a question on choice, commit 43701fd)\r\n* the Pluggable USB module inherits most of the code from old HID and replaces its functions with hooks\r\n* max additional endpoints is arbitrarily set to 12\r\n* HID, Mouse, Keyboard and MouseAndKeyboard libraries are \"generated\" from `master` code (so all code from #1803 can be merged in a second time)\r\n* a MIDIUSB library based on PluggableUSB has been added (it is a very raw porting of #2943) only to demonstrate how to plug multiple modules\r\n* `setupUSB() ` weak function has been added to `main.c` , so it will execute before `setup()` if `USBCON` is defined.\r\n\r\n_Known issues_\r\n* I'll add them here as soon as they get discovered (no doubt this list will grow soon :smile: )\r\n\r\n_How to try it_\r\nI decided not to change any provided example . If you wish to test the core, download the @ArduinoBot generated packages and modify the examples in this way:\r\n\r\nOn the top of the file:\r\n\r\n* Mouse only examples: add \r\n```C\r\n#include \"Mouse.h\"\r\n#include \"HID.h\"\r\n``` \r\n* Keyboard only examples: add \r\n```C\r\n#include \"Keyboard.h\"\r\n#include \"HID.h\"\r\n``` \r\n* Mouse and Keyboard examples: add \r\n```C\r\n#include \"MouseAndKeyboard.h\"\r\n#include \"HID.h\"\r\n``` \r\n* HID and MIDIUSB example: \r\n```arduino\r\n#include \"MIDIUSB.h\"\r\n#include \"HID.h\"\r\n#include \"Mouse.h\"\r\n\r\nvoid setupUSB() {\r\n  HID.begin();\r\n  Mouse.begin();\r\n  MidiUSB.begin();\r\n}\r\n```"},"comment":{"url":"https://api.github.com/repos/arduino/Arduino/issues/comments/114412511","html_url":"https://github.com/arduino/Arduino/pull/3304#issuecomment-114412511","issue_url":"https://api.github.com/repos/arduino/Arduino/issues/3304","id":114412511,"user":{"login":"matthijskooijman","id":194491,"avatar_url":"https://avatars.githubusercontent.com/u/194491?v=3","gravatar_id":"","url":"https://api.github.com/users/matthijskooijman","html_url":"https://github.com/matthijskooijman","followers_url":"https://api.github.com/users/matthijskooijman/followers","following_url":"https://api.github.com/users/matthijskooijman/following{/other_user}","gists_url":"https://api.github.com/users/matthijskooijman/gists{/gist_id}","starred_url":"https://api.github.com/users/matthijskooijman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matthijskooijman/subscriptions","organizations_url":"https://api.github.com/users/matthijskooijman/orgs","repos_url":"https://api.github.com/users/matthijskooijman/repos","events_url":"https://api.github.com/users/matthijskooijman/events{/privacy}","received_events_url":"https://api.github.com/users/matthijskooijman/received_events","type":"User","site_admin":false},"created_at":"2015-06-23T09:04:15Z","updated_at":"2015-06-23T09:04:15Z","body":"> However, anyone can freely overwrite it with its own non-weak implementation (like in the MIDI+HID example). Any alternative however is very welcome\r\nThe problem is that when you override the `setupUSB` function, all previous overrides will be discarded. This means that a sketch that includes multiple USB libraries, must provide its own `setupUSB` function that calls all the appropriate `begin` methods.\r\n\r\n> @matthijskooijman about the weak function, I could not imagine anything better. \r\n\r\nLooking more closely, I see you are using `setupUSB` to call e.g. `HID.begin()`, which eventually calls `PUSB_AddFunction()` to register the usb module and its callbacks. My previous suggestion, to use a callback instead of a weak `setupUSB` function of course doesn't work, since it is needed to register the callbacks in the first place.\r\n\r\nThere is a  good alternative, though: Use a global object, whose constructor calls `PUSB_AddFunction()`. Constructors of global objects are called on startup automatically.\r\n\r\nAs an example of how this works, see ModuleHandler and Module in https://github.com/Pinoccio/library-pinoccio/tree/master/src/modules Those register a Module* in a linked list inside ModuleHandler, which is the equivalent of calling `PUSB_AddFunction`\r\n\r\nOne caveat is that this all runs before `main()` is even started and the initialization order is undefined, so you should check that `PUSB_AddFunction` does not need any constructors or other initalization code to run (global variables initialized to 0 or some other constant are ok, zeroing of the .bss section and loading of the .data section happens before calling global constructor). A quick look around the code shows that this is already ok.\r\n\r\nI even think that this approach doesn't require separate libraries for every module, since the compiler can  completely remove a module, including its global constructor, if it's not referenced anywhere at all. I'm not 100% sure about this, though. And in most cases, using separate libraries is sane approach regardless of this.\r\n\r\n\r\n\r\nI had a closer look at the HID libraries, and I'm not so happy with how those look. AFAICS, the Mouse and Keyboard libraries both define a few specially-named symbols, which are then used by the HID library. This of course doesn't allow more than one HID \"submodule\", which is why there is a KeyboardAndMouse library, which is of course fairly ugly.\r\n\r\nIdeally, an approach with callbacks similar to PUSB_AddFunction is also used for HID submodules, allowing them to be completely separate from each other. However, I'm not sure if the HID descriptors are actually easy to compose (e.g. can you just concatenate or otherwise combine the Mouse and Keyboard descriptors into something valid)?"}}