This gets rid of lots of duplication of code.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
__le32 voltage;
};
-/*
- * This request only uses the connection field, and if successful,
- * fills in the major and minor protocol version of the target.
- */
-static int get_version(struct gb_battery *gb)
-{
- struct gb_battery_proto_version_response version_response;
- int retval;
-
- retval = gb_operation_sync(gb->connection,
- GB_BATTERY_TYPE_PROTOCOL_VERSION,
- NULL, 0,
- &version_response, sizeof(version_response));
- if (retval)
- return retval;
-
- if (version_response.major > GB_BATTERY_VERSION_MAJOR) {
- pr_err("unsupported major version (%hhu > %hhu)\n",
- version_response.major, GB_BATTERY_VERSION_MAJOR);
- return -ENOTSUPP;
- }
-
- gb->version_major = version_response.major;
- gb->version_minor = version_response.minor;
- return 0;
-}
+/* Define get_version() routine */
+define_get_version(gb_battery, BATTERY);
static int get_tech(struct gb_battery *gb)
{
/* debounce response has no payload */
-/*
- * This request only uses the connection field, and if successful,
- * fills in the major and minor protocol version of the target.
- */
-static int gb_gpio_proto_version_operation(struct gb_gpio_controller *ggc)
-{
- struct gb_gpio_proto_version_response response;
- int ret;
-
- ret = gb_operation_sync(ggc->connection, GB_GPIO_TYPE_PROTOCOL_VERSION,
- NULL, 0, &response, sizeof(response));
- if (ret)
- return ret;
-
- if (response.major > GB_GPIO_VERSION_MAJOR) {
- pr_err("unsupported major version (%hhu > %hhu)\n",
- response.major, GB_GPIO_VERSION_MAJOR);
- return -ENOTSUPP;
- }
- ggc->version_major = response.major;
- ggc->version_minor = response.minor;
- return 0;
-}
+/* Define get_version() routine */
+define_get_version(gb_gpio_controller, GPIO);
static int gb_gpio_line_count_operation(struct gb_gpio_controller *ggc)
{
int ret;
/* First thing we need to do is check the version */
- ret = gb_gpio_proto_version_operation(gb_gpio_controller);
+ ret = get_version(gb_gpio_controller);
if (ret)
; /* return ret; */
__u8 data[0]; /* inbound data */
};
-/*
- * This request only uses the connection field, and if successful,
- * fills in the major and minor protocol version of the target.
- */
-static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev)
-{
- struct gb_i2c_proto_version_response response;
- int ret;
-
- ret = gb_operation_sync(gb_i2c_dev->connection,
- GB_I2C_TYPE_PROTOCOL_VERSION,
- NULL, 0, &response, sizeof(response));
- if (ret)
- return ret;
-
- if (response.major > GB_I2C_VERSION_MAJOR) {
- pr_err("unsupported major version (%hhu > %hhu)\n",
- response.major, GB_I2C_VERSION_MAJOR);
- return -ENOTSUPP;
- }
- gb_i2c_dev->version_major = response.major;
- gb_i2c_dev->version_minor = response.minor;
- return 0;
-}
+/* Define get_version() routine */
+define_get_version(gb_i2c_device, I2C);
/*
* Map Greybus i2c functionality bits into Linux ones
int ret;
/* First thing we need to do is check the version */
- ret = gb_i2c_proto_version_operation(gb_i2c_dev);
+ ret = get_version(gb_i2c_dev);
if (ret)
return ret;
return protocol;
}
+int gb_protocol_get_version(struct gb_connection *connection, int type,
+ void *request, int request_size,
+ struct gb_protocol_version_response *response,
+ __u8 major)
+{
+ int retval;
+
+ retval = gb_operation_sync(connection, type, request, request_size,
+ response, sizeof(*response));
+ if (retval)
+ return retval;
+
+ if (response->major > major) {
+ dev_err(&connection->dev,
+ "unsupported major version (%hhu > %hhu)\n",
+ response->major, major);
+ return -ENOTSUPP;
+ }
+
+ dev_dbg(&connection->dev, "version_major = %u version_minor = %u\n",
+ response->major, response->minor);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(gb_protocol_get_version);
+
void gb_protocol_put(struct gb_protocol *protocol)
{
u8 major;
struct gb_operation;
+/* version request has no payload */
+struct gb_protocol_version_response {
+ __u8 major;
+ __u8 minor;
+};
+
typedef int (*gb_connection_init_t)(struct gb_connection *);
typedef void (*gb_connection_exit_t)(struct gb_connection *);
typedef void (*gb_request_recv_t)(u8, struct gb_operation *);
__gb_protocol_register(protocol, THIS_MODULE)
struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor);
+int gb_protocol_get_version(struct gb_connection *connection, int type,
+ void *request, int request_size,
+ struct gb_protocol_version_response *response,
+ __u8 major);
+
void gb_protocol_put(struct gb_protocol *protocol);
/*
} \
module_exit(protocol_exit);
+/*
+ * Macro to create get_version() routine for protocols
+ * @__device: name of the device struct
+ * @__protocol: name of protocol in CAPITALS
+ */
+#define define_get_version(__device, __protocol) \
+static int get_version(struct __device *dev) \
+{ \
+ struct gb_protocol_version_response response; \
+ int retval; \
+ \
+ retval = gb_protocol_get_version(dev->connection, \
+ GB_##__protocol##_TYPE_PROTOCOL_VERSION,\
+ NULL, 0, &response, \
+ GB_##__protocol##_VERSION_MAJOR); \
+ if (retval) \
+ return retval; \
+ \
+ dev->version_major = response.major; \
+ dev->version_minor = response.minor; \
+ return 0; \
+}
+
#endif /* __PROTOCOL_H */
__u8 which;
};
-/*
- * This request only uses the connection field, and if successful,
- * fills in the major and minor protocol version of the target.
- */
-static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc)
-{
- struct gb_pwm_proto_version_response response;
- int ret;
-
- ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PROTOCOL_VERSION,
- NULL, 0, &response, sizeof(response));
-
- if (ret)
- return ret;
-
- if (response.major > GB_PWM_VERSION_MAJOR) {
- pr_err("unsupported major version (%hhu > %hhu)\n",
- response.major, GB_PWM_VERSION_MAJOR);
- return -ENOTSUPP;
- }
- pwmc->version_major = response.major;
- pwmc->version_minor = response.minor;
- return 0;
-}
+/* Define get_version() routine */
+define_get_version(gb_pwm_chip, PWM);
static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc)
{
connection->private = pwmc;
/* Check for compatible protocol version */
- ret = gb_pwm_proto_version_operation(pwmc);
+ ret = get_version(pwmc);
if (ret)
goto out_err;
static DEFINE_MUTEX(table_lock);
static atomic_t reference_count = ATOMIC_INIT(0);
-/*
- * This request only uses the connection field, and if successful,
- * fills in the major and minor protocol version of the target.
- */
-static int get_version(struct gb_tty *tty)
-{
- struct gb_uart_proto_version_response response;
- int ret;
-
- ret = gb_operation_sync(tty->connection,
- GB_UART_TYPE_PROTOCOL_VERSION,
- NULL, 0, &response, sizeof(response));
- if (ret)
- return ret;
-
- if (response.major > GB_UART_VERSION_MAJOR) {
- pr_err("unsupported major version (%hhu > %hhu)\n",
- response.major, GB_UART_VERSION_MAJOR);
- return -ENOTSUPP;
- }
- tty->version_major = response.major;
- tty->version_minor = response.minor;
-
- pr_debug("%s: version_major = %u version_minor = %u\n",
- __func__, tty->version_major, tty->version_minor);
- return 0;
-}
+/* Define get_version() routine */
+define_get_version(gb_tty, UART);
static int send_data(struct gb_tty *tty, u16 size, const u8 *data)
{
#define to_gb_usb_device(d) ((struct gb_usb_device*) d->hcd_priv)
-static int get_version(struct gb_usb_device *dev)
-{
- struct gb_usb_proto_version_response response;
- int ret;
-
- ret = gb_operation_sync(dev->connection,
- GB_USB_TYPE_PROTOCOL_VERSION,
- NULL, 0, &response, sizeof(response));
- if (ret)
- return ret;
-
- if (response.major > GB_USB_VERSION_MAJOR) {
- pr_err("unsupported major version (%hhu > %hhu)\n",
- response.major, GB_USB_VERSION_MAJOR);
- return -ENOTSUPP;
- }
- dev->version_major = response.major;
- dev->version_minor = response.minor;
- return 0;
-}
+/* Define get_version() routine */
+define_get_version(gb_usb_device, USB);
static void hcd_stop(struct usb_hcd *hcd)
{
__le16 timeout_ms;
};
-/*
- * This request only uses the connection field, and if successful,
- * fills in the major and minor protocol version of the target.
- */
-static int get_version(struct gb_vibrator_device *vib)
-{
- struct gb_connection *connection = vib->connection;
- struct gb_vibrator_proto_version_response version_response;
- int retval;
-
- retval = gb_operation_sync(connection,
- GB_VIBRATOR_TYPE_PROTOCOL_VERSION,
- NULL, 0,
- &version_response, sizeof(version_response));
- if (retval)
- return retval;
-
- if (version_response.major > GB_VIBRATOR_VERSION_MAJOR) {
- dev_err(&connection->dev,
- "unsupported major version (%hhu > %hhu)\n",
- version_response.major, GB_VIBRATOR_VERSION_MAJOR);
- return -ENOTSUPP;
- }
-
- vib->version_major = version_response.major;
- vib->version_minor = version_response.minor;
- return 0;
-}
+/* Define get_version() routine */
+define_get_version(gb_vibrator_device, VIBRATOR);
static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
{