HelenOS sources
This source file includes following definitions.
- usb_add_match_id
- usb_device_create_match_ids_from_interface
- usb_device_create_match_ids_from_device_descriptor
- usb_device_create_match_ids
#include <usb/dev/pipes.h>
#include <usb/dev/recognise.h>
#include <usb/dev/request.h>
#include <usb/classes/classes.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#define BCD_INT(a) (((unsigned int)(a)) / 256)
#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
#define BCD_FMT "%x.%x"
#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
static errno_t usb_add_match_id(match_id_list_t *matches, int score,
char *match_str)
{
assert(matches);
match_id_t *match_id = create_match_id();
if (match_id == NULL) {
return ENOMEM;
}
match_id->id = match_str;
match_id->score = score;
add_match_id(matches, match_id);
return EOK;
}
#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
do { \
char *str = NULL; \
int __rc = asprintf(&str, format, ##__VA_ARGS__); \
if (__rc >= 0) { \
errno_t __rc = usb_add_match_id((match_ids), (score), str); \
if (__rc != EOK) { \
free(str); \
return __rc; \
} \
} else { \
return ENOMEM; \
} \
} while (0)
errno_t usb_device_create_match_ids_from_interface(
const usb_standard_device_descriptor_t *desc_device,
const usb_standard_interface_descriptor_t *desc_interface,
match_id_list_t *matches)
{
if (desc_interface == NULL || matches == NULL) {
return EINVAL;
}
if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {
return ENOENT;
}
const char *classname = usb_str_class(desc_interface->interface_class);
assert(classname != NULL);
#define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"
#define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \
desc_interface->interface_protocol
#define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"
#define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass
#define IFACE_CLASS_FMT "interface&class=%s"
#define IFACE_CLASS_ARGS classname
#define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT
#define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \
BCD_ARGS(desc_device->device_version)
#define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"
#define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id
#define VENDOR_ONLY_FMT "vendor=0x%04x"
#define VENDOR_ONLY_ARGS desc_device->vendor_id
if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {
ADD_MATCHID_OR_RETURN(matches, 250,
"usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,
VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);
ADD_MATCHID_OR_RETURN(matches, 240,
"usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,
VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);
ADD_MATCHID_OR_RETURN(matches, 230,
"usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,
VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);
ADD_MATCHID_OR_RETURN(matches, 220,
"usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,
VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);
ADD_MATCHID_OR_RETURN(matches, 210,
"usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,
VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);
ADD_MATCHID_OR_RETURN(matches, 200,
"usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,
VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);
ADD_MATCHID_OR_RETURN(matches, 190,
"usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,
VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);
ADD_MATCHID_OR_RETURN(matches, 180,
"usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,
VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);
ADD_MATCHID_OR_RETURN(matches, 170,
"usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,
VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);
}
ADD_MATCHID_OR_RETURN(matches, 160,
"usb&" IFACE_PROTOCOL_FMT,
IFACE_PROTOCOL_ARGS);
ADD_MATCHID_OR_RETURN(matches, 150,
"usb&" IFACE_SUBCLASS_FMT,
IFACE_SUBCLASS_ARGS);
ADD_MATCHID_OR_RETURN(matches, 140,
"usb&" IFACE_CLASS_FMT,
IFACE_CLASS_ARGS);
#undef IFACE_PROTOCOL_FMT
#undef IFACE_PROTOCOL_ARGS
#undef IFACE_SUBCLASS_FMT
#undef IFACE_SUBCLASS_ARGS
#undef IFACE_CLASS_FMT
#undef IFACE_CLASS_ARGS
#undef VENDOR_RELEASE_FMT
#undef VENDOR_RELEASE_ARGS
#undef VENDOR_PRODUCT_FMT
#undef VENDOR_PRODUCT_ARGS
#undef VENDOR_ONLY_FMT
#undef VENDOR_ONLY_ARGS
ADD_MATCHID_OR_RETURN(matches, 10, "usb&interface&fallback");
return EOK;
}
errno_t usb_device_create_match_ids_from_device_descriptor(
const usb_standard_device_descriptor_t *device_descriptor,
match_id_list_t *matches)
{
if (device_descriptor->vendor_id != 0) {
ADD_MATCHID_OR_RETURN(matches, 100,
"usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
(int) device_descriptor->vendor_id,
(int) device_descriptor->product_id,
BCD_ARGS(device_descriptor->device_version));
ADD_MATCHID_OR_RETURN(matches, 90,
"usb&vendor=0x%04x&product=0x%04x",
(int) device_descriptor->vendor_id,
(int) device_descriptor->product_id);
}
ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
usb_str_class(device_descriptor->device_class));
ADD_MATCHID_OR_RETURN(matches, 10, "usb&fallback");
return EOK;
}
errno_t usb_device_create_match_ids(usb_pipe_t *ctrl_pipe,
match_id_list_t *matches)
{
assert(ctrl_pipe);
errno_t rc;
usb_standard_device_descriptor_t device_descriptor;
rc = usb_request_get_device_descriptor(ctrl_pipe, &device_descriptor);
if (rc != EOK) {
return rc;
}
rc = usb_device_create_match_ids_from_device_descriptor(
&device_descriptor, matches);
if (rc != EOK) {
return rc;
}
return EOK;
}
HelenOS homepage, sources at GitHub