Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions arch/arm/configs/ev3dev_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ CONFIG_SND=m
# CONFIG_SND_VERBOSE_PROCFS is not set
CONFIG_SND_LEGOEV3=m
CONFIG_SND_USB_AUDIO=m
CONFIG_HID=y
CONFIG_HIDRAW=y
CONFIG_HID_GENERIC=y
CONFIG_USB=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
Expand All @@ -172,6 +175,7 @@ CONFIG_USB_SERIAL_CP210X=m
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_LEGOTOWER=m
CONFIG_USB_LEGOWEDO=m
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
Expand Down
94 changes: 69 additions & 25 deletions drivers/legoev3/dc_motor_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* DC motor device class for LEGO MINDSTORMS EV3
*
* Copyright (C) 2014 David Lechner <david@lechnology.com>
* Copyright (C) 2014 Ralph Hempel <rhempel@hempeldesigngroup.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
Expand Down Expand Up @@ -42,9 +43,13 @@
* `commands` (read-only)
* : Returns a space separated list of commands supported by the motor controller.
* .
* `duty_cycle` (read/write)
* : Sets the duty cycle of the PWM signal sent to the motor. Values are -100
* to 100 (-100% to 100%).
* `duty_cycle_sp` (read/write)
* : Sets the duty cycle setpoint of the PWM signal sent to the motor. Values
* -100 to 100 (-100% to 100%).
* .
* `duty_cycle` (read)
* : Shows the current duty cycle of the PWM signal sent to the motor. Values
* -100 to 100 (-100% to 100%).
* .
* `name` (read-only)
* : Returns the name of the motor controller's driver.
Expand Down Expand Up @@ -89,7 +94,7 @@ enum hrtimer_restart dc_motor_class_ramp_timer_handler(struct hrtimer *timer)
{
struct dc_motor_device *motor =
container_of(timer, struct dc_motor_device, ramp_timer);
int ramp_ns, err;
int ramp_ns, err, direction;

if (motor->current_duty_cycle == motor->target_duty_cycle)
return HRTIMER_NORESTART;
Expand All @@ -101,10 +106,24 @@ enum hrtimer_restart dc_motor_class_ramp_timer_handler(struct hrtimer *timer)
ramp_ns = motor->ramp_down_ms * 10000;
motor->current_duty_cycle--;
}

if (0 == ramp_ns)
motor->current_duty_cycle = motor->target_duty_cycle;

hrtimer_forward_now(&motor->ramp_timer, ktime_set(0, ramp_ns));
err = motor->ops.set_polarity(motor->ops.context,
motor->polarity ^ (motor->current_duty_cycle < 0));
WARN_ONCE(err, "Failed to set polarity.");

if (motor->polarity == DC_MOTOR_POLARITY_NORMAL )
direction = (motor->current_duty_cycle >= 0)
? DC_MOTOR_DIRECTION_FORWARD
: DC_MOTOR_DIRECTION_REVERSE;
else
direction = (motor->current_duty_cycle <= 0)
? DC_MOTOR_DIRECTION_FORWARD
: DC_MOTOR_DIRECTION_REVERSE;

err = motor->ops.set_direction(motor->ops.context, direction );
WARN_ONCE(err, "Failed to set direction.");

err = motor->ops.set_duty_cycle(motor->ops.context,
abs(motor->current_duty_cycle));
WARN_ONCE(err, "Failed to set duty cycle.");
Expand Down Expand Up @@ -146,7 +165,6 @@ static ssize_t ramp_up_ms_store(struct device *dev,
if (sscanf(buf, "%ud", &value) != 1 || value > 10000)
return -EINVAL;
motor->ramp_up_ms = value;
/* TODO: need to implement ramping */

return count;
}
Expand All @@ -169,7 +187,6 @@ static ssize_t ramp_down_ms_store(struct device *dev,
if (sscanf(buf, "%ud", &value) != 1 || value > 10000)
return -EINVAL;
motor->ramp_down_ms = value;
/* TODO: need to implement ramping */

return count;
}
Expand All @@ -186,49 +203,74 @@ static ssize_t polarity_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dc_motor_device *motor = to_dc_motor_device(dev);
int i, err;
int i;

for (i = 0; i < NUM_DC_MOTOR_POLARITY; i++) {
if (sysfs_streq(buf, dc_motor_polarity_values[i])) {
err = motor->ops.set_polarity(motor->ops.context, i);
if (err)
return err;
motor->polarity = i;
if (motor->polarity != i) {
/*
* Force the motor state to get re-evaluated when
* timer expires, makes the motor use ramping even
* if we change direction mid-flight
*/
motor->current_duty_cycle = -motor->current_duty_cycle;

motor->polarity = i;
hrtimer_start(&motor->ramp_timer,
ktime_set(0, 0), HRTIMER_MODE_REL);
}
return count;
}

}
return -EINVAL;
}

static ssize_t duty_cycle_show(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t duty_cycle_sp_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dc_motor_device *motor = to_dc_motor_device(dev);
int duty_cycle;
int duty_cycle_sp;

duty_cycle = motor->ops.get_duty_cycle(motor->ops.context);
if (motor->polarity == DC_MOTOR_POLARITY_INVERTED)
duty_cycle = -duty_cycle;
return sprintf(buf, "%d\n", duty_cycle);
duty_cycle_sp = motor->target_duty_cycle;
return sprintf(buf, "%d\n", duty_cycle_sp);
}

static ssize_t duty_cycle_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
static ssize_t duty_cycle_sp_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct dc_motor_device *motor = to_dc_motor_device(dev);
int value;

if (sscanf(buf, "%d", &value) != 1 || value < -100 || value > 100)
return -EINVAL;
motor->target_duty_cycle = value;

if (motor->ops.get_command(motor->ops.context) == DC_MOTOR_COMMAND_RUN)
hrtimer_start(&motor->ramp_timer, ktime_set(0, 0), HRTIMER_MODE_REL);

return count;
}

static ssize_t duty_cycle_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dc_motor_device *motor = to_dc_motor_device(dev);
int duty_cycle;
unsigned direction;
unsigned polarity;

duty_cycle = motor->ops.get_duty_cycle(motor->ops.context);
direction = motor->ops.get_direction(motor->ops.context);
polarity = motor->polarity;

duty_cycle *= ((direction == DC_MOTOR_DIRECTION_FORWARD) ? 1 : -1);
duty_cycle *= ((polarity == DC_MOTOR_POLARITY_NORMAL) ? 1 : -1);

return sprintf(buf, "%d\n", duty_cycle);
}

static ssize_t commands_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
Expand Down Expand Up @@ -294,7 +336,8 @@ static DEVICE_ATTR_RO(port_name);
static DEVICE_ATTR_RW(ramp_up_ms);
static DEVICE_ATTR_RW(ramp_down_ms);
static DEVICE_ATTR_RW(polarity);
static DEVICE_ATTR_RW(duty_cycle);
static DEVICE_ATTR_RW(duty_cycle_sp);
static DEVICE_ATTR_RO(duty_cycle);
static DEVICE_ATTR_RO(commands);
static DEVICE_ATTR_RW(command);

Expand All @@ -304,6 +347,7 @@ static struct attribute *dc_motor_class_attrs[] = {
&dev_attr_ramp_up_ms.attr,
&dev_attr_ramp_down_ms.attr,
&dev_attr_polarity.attr,
&dev_attr_duty_cycle_sp.attr,
&dev_attr_duty_cycle.attr,
&dev_attr_commands.attr,
&dev_attr_command.attr,
Expand Down
22 changes: 11 additions & 11 deletions drivers/legoev3/ev3_output_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,14 @@ struct ev3_output_port_data {
struct legoev3_port_device *motor;
enum ev3_output_port_mode mode;
enum dc_motor_command command;
enum dc_motor_polarity polarity;
enum dc_motor_direction direction;
};

int ev3_output_port_set_direction_gpios(struct ev3_output_port_data *data)
{
switch(data->command) {
case DC_MOTOR_COMMAND_RUN:
if (data->polarity == DC_MOTOR_POLARITY_NORMAL) {
if (data->direction == DC_MOTOR_DIRECTION_FORWARD) {
gpio_direction_output(data->gpio[GPIO_PIN1].gpio, 1);
gpio_direction_input(data->gpio[GPIO_PIN2].gpio);
} else {
Expand Down Expand Up @@ -293,7 +293,7 @@ static unsigned ev3_ouput_port_get_supported_commands(void* context)
| BIT(DC_MOTOR_COMMAND_BRAKE);
}

static int ev3_output_port_get_command(void *context)
static enum dc_motor_command ev3_output_port_get_command(void *context)
{
struct ev3_output_port_data *data = context;

Expand All @@ -312,21 +312,21 @@ static int ev3_output_port_set_command(void *context,
return ev3_output_port_set_direction_gpios(data);
}

static enum dc_motor_polarity ev3_output_port_get_polarity(void *context)
static enum dc_motor_direction ev3_output_port_get_direction(void *context)
{
struct ev3_output_port_data *data = context;

return data->polarity;
return data->direction;
}

static int ev3_output_port_set_polarity(void *context,
enum dc_motor_polarity polarity)
static int ev3_output_port_set_direction(void *context,
enum dc_motor_direction direction)
{
struct ev3_output_port_data *data = context;

if (data->polarity == polarity)
if (data->direction == direction)
return 0;
data->polarity = polarity;
data->direction = direction;

return ev3_output_port_set_direction_gpios(data);
}
Expand Down Expand Up @@ -386,8 +386,8 @@ void ev3_output_port_register_motor(struct work_struct *work)
ev3_ouput_port_get_supported_commands;
pdata.motor_ops.get_command = ev3_output_port_get_command;
pdata.motor_ops.set_command = ev3_output_port_set_command;
pdata.motor_ops.get_polarity = ev3_output_port_get_polarity;
pdata.motor_ops.set_polarity = ev3_output_port_set_polarity;
pdata.motor_ops.get_direction = ev3_output_port_get_direction;
pdata.motor_ops.set_direction = ev3_output_port_set_direction;
pdata.motor_ops.set_duty_cycle = ev3_output_port_set_duty_cycle;
pdata.motor_ops.get_duty_cycle = ev3_output_port_get_duty_cycle;
pdata.motor_ops.context = data;
Expand Down
4 changes: 2 additions & 2 deletions drivers/legoev3/ev3_tacho_motor.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,14 @@ void ev3_tacho_motor_update_output(struct ev3_tacho_motor_data *ev3_tm)
int err;

if (ev3_tm->power > 0) {
pdata->motor_ops.set_polarity(pdata->motor_ops.context,
pdata->motor_ops.set_direction(pdata->motor_ops.context,
ev3_tm->polarity_mode);
pdata->motor_ops.set_command(pdata->motor_ops.context,
DC_MOTOR_COMMAND_RUN);
if (ev3_tm->regulation_mode == TM_REGULATION_OFF && ev3_tm->power < 10)
ev3_tm->power = 10;
} else if (ev3_tm->power < 0) {
pdata->motor_ops.set_polarity(pdata->motor_ops.context,
pdata->motor_ops.set_direction(pdata->motor_ops.context,
!ev3_tm->polarity_mode);
pdata->motor_ops.set_command(pdata->motor_ops.context,
DC_MOTOR_COMMAND_RUN);
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/misc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ config USB_APPLEDISPLAY

source "drivers/usb/misc/sisusbvga/Kconfig"

source "drivers/usb/misc/wedo/Kconfig"

config USB_LD
tristate "USB LD driver"
help
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/misc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ obj-$(CONFIG_USB_LCD) += usblcd.o
obj-$(CONFIG_USB_LD) += ldusb.o
obj-$(CONFIG_USB_LED) += usbled.o
obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o
obj-$(CONFIG_USB_LEGOWEDO) += wedo/
obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_TEST) += usbtest.o
obj-$(CONFIG_USB_EHSET_TEST_FIXTURE) += ehset.o
Expand Down
13 changes: 13 additions & 0 deletions drivers/usb/misc/wedo/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# LEGO WeDo device driver

menuconfig USB_LEGOWEDO
tristate "LEGO WeDo support"
depends on USB
select LEGOEV3_MSENSORS
select LEGOEV3_DC_MOTORS
help
Say Y here if you want to connect a LEGO WeDo hub to your USB
ports.

To compile this driver as a module, choose M here: the
module will be called legowedo.
7 changes: 7 additions & 0 deletions drivers/usb/misc/wedo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Makefile for the LEGO WeDo driver (if driver is inside kernel tree).
#

obj-$(CONFIG_USB_LEGOWEDO) += legousbwedo.o

legousbwedo-y := legowedo.o wedo_hub.o wedo_port.o wedo_sensor.o wedo_motor.o
Loading