Allow opening of USB device by physical bus path
In case there are multiple devices with identical VID/PID, the existing open_vid_pid mechanism is insufficient.
This commit is contained in:
parent
49858b1a66
commit
4c742e931a
|
@ -18,8 +18,12 @@ type record USB_Device_Match_vidpid {
|
||||||
HEX4n vid,
|
HEX4n vid,
|
||||||
HEX4n pid
|
HEX4n pid
|
||||||
};
|
};
|
||||||
|
type record USB_Device_Match_path {
|
||||||
|
charstring path
|
||||||
|
};
|
||||||
type union USB_Device_Match {
|
type union USB_Device_Match {
|
||||||
USB_Device_Match_vidpid vid_pid
|
USB_Device_Match_vidpid vid_pid,
|
||||||
|
USB_Device_Match_path path
|
||||||
};
|
};
|
||||||
|
|
||||||
function f_usb_init_vid_pid(HEX4n vendor_id, HEX4n product_id) runs on USB_CT {
|
function f_usb_init_vid_pid(HEX4n vendor_id, HEX4n product_id) runs on USB_CT {
|
||||||
|
@ -41,10 +45,35 @@ function f_usb_init_vid_pid(HEX4n vendor_id, HEX4n product_id) runs on USB_CT {
|
||||||
g_USB_Tguard.stop;
|
g_USB_Tguard.stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function f_usb_init_path(charstring path) runs on USB_CT {
|
||||||
|
map(self:USB, system:USB);
|
||||||
|
var USB_result res;
|
||||||
|
var integer req_hdl := f_usb_get_req_hdl();
|
||||||
|
USB.send(ts_USB_open_path(path, device_hdl := g_dev_hdl, req_hdl := req_hdl));
|
||||||
|
g_USB_Tguard.start;
|
||||||
|
alt {
|
||||||
|
[] USB.receive(tr_USB_result(req_hdl := req_hdl, device_hdl := g_dev_hdl)) -> value res {
|
||||||
|
log("Received ", res);
|
||||||
|
}
|
||||||
|
[] USB.receive {
|
||||||
|
testcase.stop("Couldn't open requested USB device");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_USB_Tguard.stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private altstep as_Tguard() runs on USB_CT {
|
||||||
|
[] g_USB_Tguard.timeout {
|
||||||
|
testcase.stop("Timeout of global USB guard timer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function f_usb_init(USB_Device_Match udm) runs on USB_CT {
|
function f_usb_init(USB_Device_Match udm) runs on USB_CT {
|
||||||
activate(as_Tguard());
|
activate(as_Tguard());
|
||||||
if (ischosen(udm.vid_pid)) {
|
if (ischosen(udm.vid_pid)) {
|
||||||
f_usb_init_vid_pid(udm.vid_pid.vid, udm.vid_pid.pid);
|
f_usb_init_vid_pid(udm.vid_pid.vid, udm.vid_pid.pid);
|
||||||
|
} else if (ischosen(udm.path)) {
|
||||||
|
f_usb_init_path(udm.path.path);
|
||||||
} else {
|
} else {
|
||||||
testcase.stop("Unsupported USB_Device_Match");
|
testcase.stop("Unsupported USB_Device_Match");
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,6 +343,67 @@ void USB__PT_PROVIDER::outgoing_send(const USB__open__vid__pid& send_par)
|
||||||
incoming_message(USB__result(send_par.req__hdl(), send_par.device__hdl(), rc));
|
incoming_message(USB__result(send_par.req__hdl(), send_par.device__hdl(), rc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stringify_usb_path(char *out, uint8_t bus_num, const uint8_t *ports, size_t num_ports)
|
||||||
|
{
|
||||||
|
int length = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
length += sprintf(out, "%u-%u", bus_num, ports[0]);
|
||||||
|
for (i = 1; i < num_ports; i++)
|
||||||
|
length += sprintf(out+length, ".%u", ports[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB__PT_PROVIDER::outgoing_send(const USB__open__path& send_par)
|
||||||
|
{
|
||||||
|
unsigned int device_hdl = send_par.device__hdl();
|
||||||
|
const CHARSTRING &in_path_char = send_par.path();
|
||||||
|
const char *in_path = (const char *) in_path_char;
|
||||||
|
libusb_device_handle *dh = NULL;
|
||||||
|
libusb_device **list;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
|
rc = libusb_get_device_list(mCtx, &list);
|
||||||
|
if (rc < 0) {
|
||||||
|
log("Error getting USB device list: %s\n",
|
||||||
|
libusb_strerror((enum libusb_error) rc));
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; list[i] != NULL; i++) {
|
||||||
|
uint8_t ports[8];
|
||||||
|
char path[256];
|
||||||
|
libusb_device *dev = list[i];
|
||||||
|
rc = libusb_get_port_numbers(dev, ports, sizeof(ports));
|
||||||
|
stringify_usb_path(path, libusb_get_bus_number(dev), ports, rc);
|
||||||
|
log("Found USB Device at path %s", path);
|
||||||
|
if (!strcmp(in_path, path)) {
|
||||||
|
rc = libusb_open(dev, &dh);
|
||||||
|
if (rc < 0) {
|
||||||
|
log("Error opening USB device %s: %s", path,
|
||||||
|
libusb_strerror((enum libusb_error) rc));
|
||||||
|
rc = -1;
|
||||||
|
} else {
|
||||||
|
USB_Device *udev = new USB_Device(this, dh, device_hdl);
|
||||||
|
mDevices.insert(std::make_pair(device_hdl, udev));
|
||||||
|
log("Successfully opened USB device at path %s", path);
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dh) {
|
||||||
|
log("No matching USB device for %s", in_path);
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
libusb_free_device_list(list, 1);
|
||||||
|
|
||||||
|
out:
|
||||||
|
incoming_message(USB__result(send_par.req__hdl(), send_par.device__hdl(), rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void USB__PT_PROVIDER::outgoing_send(const USB__set__configuration& send_par)
|
void USB__PT_PROVIDER::outgoing_send(const USB__set__configuration& send_par)
|
||||||
{
|
{
|
||||||
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
USB_Device *dev = usbdev_by_hdl(send_par.device__hdl());
|
||||||
|
|
|
@ -94,6 +94,7 @@ protected:
|
||||||
void user_stop();
|
void user_stop();
|
||||||
|
|
||||||
void outgoing_send(const USB__open__vid__pid& send_par);
|
void outgoing_send(const USB__open__vid__pid& send_par);
|
||||||
|
void outgoing_send(const USB__open__path& send_par);
|
||||||
void outgoing_send(const USB__transfer& send_par);
|
void outgoing_send(const USB__transfer& send_par);
|
||||||
void outgoing_send(const USB__set__configuration& send_par);
|
void outgoing_send(const USB__set__configuration& send_par);
|
||||||
void outgoing_send(const USB__claim__interface& send_par);
|
void outgoing_send(const USB__claim__interface& send_par);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import from USB_PortTypes all;
|
||||||
|
|
||||||
type port USB_PT message {
|
type port USB_PT message {
|
||||||
out USB_open_vid_pid;
|
out USB_open_vid_pid;
|
||||||
|
out USB_open_path;
|
||||||
out USB_set_configuration;
|
out USB_set_configuration;
|
||||||
out USB_claim_interface;
|
out USB_claim_interface;
|
||||||
out USB_release_interface;
|
out USB_release_interface;
|
||||||
|
|
|
@ -60,6 +60,14 @@ module USB_PortTypes {
|
||||||
};
|
};
|
||||||
/* Response: USB_result */
|
/* Response: USB_result */
|
||||||
|
|
||||||
|
type record USB_open_path {
|
||||||
|
integer req_hdl,
|
||||||
|
integer device_hdl,
|
||||||
|
charstring path
|
||||||
|
};
|
||||||
|
/* Response: USB_result */
|
||||||
|
|
||||||
|
|
||||||
type record USB_set_configuration {
|
type record USB_set_configuration {
|
||||||
integer req_hdl,
|
integer req_hdl,
|
||||||
integer device_hdl,
|
integer device_hdl,
|
||||||
|
@ -132,6 +140,14 @@ ts_USB_open_vid_pid(USB_vendor_id vid, USB_product_id pid, integer device_hdl :=
|
||||||
product_id := pid
|
product_id := pid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template (value) USB_open_path
|
||||||
|
ts_USB_open_path(charstring path, integer device_hdl := -1, integer req_hdl := -1) := {
|
||||||
|
req_hdl := req_hdl,
|
||||||
|
device_hdl := device_hdl,
|
||||||
|
path := path
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template USB_result tr_USB_result(template integer req_hdl := ?, template integer device_hdl := ?,
|
template USB_result tr_USB_result(template integer req_hdl := ?, template integer device_hdl := ?,
|
||||||
template integer result_code := ?) := {
|
template integer result_code := ?) := {
|
||||||
req_hdl := req_hdl,
|
req_hdl := req_hdl,
|
||||||
|
|
Loading…
Reference in New Issue