OK, let's try to strike the iron while it's hot, and get an idea of how we could implement these platform/OS specific calls. And since I'm interested in finding out if there exists a best approach for these kind of implementations, I'm gonna use a fairly concrete example of what we may want to contend with, so that it's hopefully easier to point out what works or doesn't work.
So let's say we want to add a call for OS1 to be able to set/get prop_os1_a, prop_os1_b and prop_os1_c, with prop_os1_[a-c] ranging from regular C type, such as int, to platform specific structs or enums. Now, unlike what will be the case in this example set and get are never gonna be balanced, but it may help the discussion to consider we have both a get and set for the same attribute. Now, let's assume: - prop_os1_a = int value, not relying on additional external header (i.e. straight numeric) - prop_os1_b = os1_enum, defined in os1_enum.h - prop_os1_c = struct os1_struct_t = { os1_enum, os1_type, char* }, with os1_struct (and os1_type) defined in os1_types.h. We may also want to consider that there's a fair chance os1_struct could be extended in the next iteration of the OS. More specifically, I'm thinking about the obnoxious _EX Microsoftisms, which we had to contend with internally in the Windows backend, with regards to retrieving USB speeds (For an idea of the typical Windows landscape in that matter, just know that there currently exists an USB_NODE_CONNECTION_INFORMATION, an USB_NODE_CONNECTION_INFORMATION_EX as well as an USB_NODE_CONNECTION_INFORMATION_EX_V2). And to make things even more fun, I'm gonna add that, on get, the char* of prop_os1 is a string allocated by the OS, through the os1_get_string_prop() API call, and that the OS requires us to free it with an os1_free_string_prop() OS API call. For the sake of completion, I'm also gonna add OS2, with a single prop_os2 value, as a numeric int, that we also want to be able to get/set. At the moment, my take on this would be to go with the following (bear in mind that this is only an RFC) ------------------------------------------------------------------- #if defined(OS1) #include <os1_type.h> #include <os1_enum.h> enum { libusb_get_prop_os1_a, // Some of those would be dropped libusb_set_prop_os1_a, // according to what we can get/set libusb_get_prop_os1_b, libusb_set_prop_os1_b, libusb_get_prop_os1_c, libusb_set_prop_os1_c, } libusb_os_prop_op; struct { enum libusb_os_prop_op op; int *prop_os1_a; int *prop_os1_b; struct os1_struct *prop_os1_c; // + whatever additional attributes may need to be // fed to the OS to get some props. eg: int *prop_os1_c_query_params; } libusb_os_props; #elif defined(OS2) #include <os2_whatever.h> enum { libusb_get_prop_os2, libusb_set_prop_os2, } libusb_os_prop_op; struct { enum libusb_os_prop_op op; int *prop_os2; // + additional props query specifics } libusb_os_props; #endif // common prototypes int libusb_rw_os_props(struct libusb_os_props *props); libusb_os_props *libusb_allocate_os_props(libusb_os_prop_op op); void libusb_free_os_props(libusb_os_props *props); ------------------------------------------------------------------- Then a libusbx app using OS1, that wants to retrieve the string in prop_os1_c would proceed as follows: ------------------------------------------------------------------- struct libusb_os_props *props; props = libusb_allocate_os_props(libusb_get_prop_os1_c); // The call above will allocate a new libusb_os_props struct, // with op set to libusb_get_prop_os1_c, and with any attribute // needed for the underlying get_prop_os1_c call also allocated // In this case, that would be an int for prop_os1_c_query_params // All other pointers, including prop_os1_c, would be NULL. // If needed, set the attribute(s) needed for get_prop_os1_c. eg: props->prop_os1_c_query_params = OS1_PROP_C_QUERY_ENUM_VAL; // The following then relies on the backend to call // os1_get_string_prop() and allocate a struct for the returned // data in prop_os1_c (along with a string in prop_os1_c itself) if (libusb_rw_os_props(props) == LIBUSB_SUCCESS) { // PROCESS props->prop_os1_c.string } libusb_free_os_props(props); // Besides freeing all elements that were allocated by libusbx, // the above would also call os1_free_string_prop() ------------------------------------------------------------------- Now, you might wonder why I choose to allocate pointers for everything, including integers. This is mostly because that the 32 bit int bitmask that the OS uses today may very well be extended to a 64 bit bitmask tomorrow, and in case a shared libusbx library is replaced with an older version, we might as well limit breakage due to shifted props attributes. In short, we want our props struct to be able to grow, as well as evolve some of its attribute in accordance to how the OS evolves them, this using pointers everywhere should allow us to evolve our props less disruptively. Finally, depending on the target of the underlying OS prop API call, we may need to add a libusbx device, or transfer, or any other relevant libusbx parameter to our props struct, but I don't consider this as much of a concern. Also, though in the Windows backend, we currently set some of the OS/driver specific properties during init, I don't exactly see a need to extent init to accept props, which we could do, when we can just issue an OS props call before or after. In other words, I don't currently envision an OS props call that would absolutely have to be carried out during init, but maybe someone can think of one. Anyway, at this stage, I'd appreciate comments on what you think the most appropriate method would be, or where you think the above proposal can break, as well as any alternative proposals you have. Regards, /Pete ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ libusbx-devel mailing list libusbx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libusbx-devel