blob: 8b7a801066cfb16952aaaeb67ca7c2ea9caefdec [file] [log] [blame]
Edward O'Callaghand3396402020-02-17 12:47:12 +11001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2020, Google Inc. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#ifndef USB_DEVICE_H
18#define USB_DEVICE_H
19
20/*
21 * USB device matching framework
22 *
23 * This can be used to match a USB device by a number of different parameters.
24 * The parameters can be passed on the command line and defaults can be set
25 * by the programmer.
26 */
27
28#include <libusb.h>
29#include <stdint.h>
Edward O'Callaghan8b191f52020-03-05 15:06:57 +110030#include <stdbool.h>
31
32/*
33 * The LIBUSB_ERROR macro converts a libusb failure code into an error code that
34 * flashrom recognizes. It does so without displaying an error code allowing us
35 * to compare error codes against the library enumeration values.
36 */
Angel Pons89261cc2021-02-28 12:07:08 +010037#define LIBUSB_ERROR(error_code) (0x20000 | -(error_code))
Edward O'Callaghand3396402020-02-17 12:47:12 +110038
39/*
40 * The LIBUSB macro converts a libusb failure code into an error code that
Edward O'Callaghan8b191f52020-03-05 15:06:57 +110041 * flashrom recognizes. It also displays additional libusb specific
Edward O'Callaghand3396402020-02-17 12:47:12 +110042 * information about the failure.
43 */
Angel Pons9635cb42021-02-28 12:40:07 +010044#define LIBUSB(expression) \
45 ({ \
46 int libusb_error__ = (expression); \
Edward O'Callaghand3396402020-02-17 12:47:12 +110047 \
Angel Pons9635cb42021-02-28 12:40:07 +010048 if (libusb_error__ < 0) { \
49 msg_perr("libusb error: %s:%d %s\n", \
50 __FILE__, \
51 __LINE__, \
52 libusb_error_name(libusb_error__)); \
Edward O'Callaghan8b191f52020-03-05 15:06:57 +110053 libusb_error__ = LIBUSB_ERROR(libusb_error__); \
Angel Pons9635cb42021-02-28 12:40:07 +010054 } else { \
55 libusb_error__ = 0; \
56 } \
Edward O'Callaghand3396402020-02-17 12:47:12 +110057 \
Angel Pons9635cb42021-02-28 12:40:07 +010058 libusb_error__; \
Edward O'Callaghand3396402020-02-17 12:47:12 +110059 })
60
61/*
Edward O'Callaghan8b191f52020-03-05 15:06:57 +110062 * Returns true if the error code falls within the range of valid libusb
63 * error codes.
64 */
65static inline bool usb_device_is_libusb_error(int error_code)
66{
Angel Pons9635cb42021-02-28 12:40:07 +010067 return (0x20000 <= error_code && error_code < 0x20064);
Edward O'Callaghan8b191f52020-03-05 15:06:57 +110068}
69
70/*
Edward O'Callaghand3396402020-02-17 12:47:12 +110071 * A USB match and associated value struct are used to encode the information
72 * about a device against which we wish to match. If the value of a
73 * usb_match_value has been set then a device must match that value. The name
74 * of the usb_match_value is used to fetch the programmer parameter from the
75 * flashrom command line and is the same as the name of the corresponding
76 * field in usb_match.
77 */
78struct usb_match_value {
79 char const *name;
80 int value;
81 int set;
82};
83
84struct usb_match {
85 struct usb_match_value bus;
86 struct usb_match_value address;
87 struct usb_match_value vid;
88 struct usb_match_value pid;
89 struct usb_match_value serial;
90 struct usb_match_value config;
91 struct usb_match_value interface;
92 struct usb_match_value altsetting;
93 struct usb_match_value class;
94 struct usb_match_value subclass;
95 struct usb_match_value protocol;
96};
97
98/*
99 * Initialize a usb_match structure so that each value's name matches the
100 * values name in the usb_match structure (so bus.name == "bus"...), and
101 * look for each value in the flashrom command line via
102 * extract_programmer_param. If the value is found convert it to an integer
103 * using strtol, accepting hex, decimal and octal encoding.
104 */
105void usb_match_init(struct usb_match *match);
106
107/*
108 * Add a default value to a usb_match_value. This must be done after calling
109 * usb_match_init. If usb_match_init already set the value of a usb_match_value
110 * we do nothing, otherwise set the value to default_value. This ensures that
111 * parameters passed on the command line override defaults.
112 */
113void usb_match_value_default(struct usb_match_value *match,
114 long int default_value);
115
116/*
117 * The usb_device structure is an entry in a linked list of devices that were
118 * matched by usb_device_find.
119 */
120struct usb_device {
121 struct libusb_device *device;
122 struct libusb_config_descriptor *config_descriptor;
123 struct libusb_interface_descriptor const *interface_descriptor;
124
125 /*
126 * Initially NULL, the libusb_device_handle is only valid once the
127 * usb_device has been successfully passed to usb_device_show or
128 * usb_device_claim.
129 */
130 struct libusb_device_handle *handle;
131
132 /*
133 * Link to next device, or NULL
134 */
135 struct usb_device *next;
136};
137
138/*
139 * Find and return a list of all compatible devices. Each device is added to
140 * the list with its first valid configuration and interface. If an alternate
141 * configuration (config, interface, altsetting...) is desired the specifics
142 * can be supplied as programmer parameters.
143 *
144 * Return:
145 * 0: At least one matching device was found.
146 * 1: No matching devices were found.
147 */
148int usb_device_find(struct usb_match const *match, struct usb_device **devices);
149
150/*
151 * Display the devices bus and address as well as its product string. The
152 * underlying libusb device is opened if it is not already open.
153 *
154 * Return:
155 * 0: The device information was displayed.
156 * non-zero: There was a failure while displaying the device information.
157 */
158int usb_device_show(char const *prefix, struct usb_device *device);
159
160/*
161 * Open the underlying libusb device, set its config, claim the interface and
162 * select the correct alternate interface.
163 *
164 * Return:
165 * 0: The device was successfully claimed.
166 * non-zero: There was a failure while trying to claim the device.
167 */
168int usb_device_claim(struct usb_device *device);
169
170/*
171 * Free a usb_device structure.
172 *
173 * This ensures that the libusb device is closed and that all allocated
174 * handles and descriptors are freed.
175 *
176 * Return:
177 * The next device in the device list.
178 */
179struct usb_device *usb_device_free(struct usb_device *device);
180
181#endif /* USB_DEVICE_H */