Commit 5014186d authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: USB devices - handle errors when registering input devices

Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent db61a912
...@@ -135,6 +135,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ ...@@ -135,6 +135,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
struct usb_acecad *acecad; struct usb_acecad *acecad;
struct input_dev *input_dev; struct input_dev *input_dev;
int pipe, maxp; int pipe, maxp;
int err = -ENOMEM;
if (interface->desc.bNumEndpoints != 1) if (interface->desc.bNumEndpoints != 1)
return -ENODEV; return -ENODEV;
...@@ -149,16 +150,22 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ ...@@ -149,16 +150,22 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL); acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!acecad || !input_dev) if (!acecad || !input_dev) {
err = -ENOMEM;
goto fail1; goto fail1;
}
acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma);
if (!acecad->data) if (!acecad->data) {
err= -ENOMEM;
goto fail1; goto fail1;
}
acecad->irq = usb_alloc_urb(0, GFP_KERNEL); acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!acecad->irq) if (!acecad->irq) {
err = -ENOMEM;
goto fail2; goto fail2;
}
acecad->usbdev = dev; acecad->usbdev = dev;
acecad->input = input_dev; acecad->input = input_dev;
...@@ -221,7 +228,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ ...@@ -221,7 +228,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
acecad->irq->transfer_dma = acecad->data_dma; acecad->irq->transfer_dma = acecad->data_dma;
acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
input_register_device(acecad->input); err = input_register_device(acecad->input);
if (err)
goto fail2;
usb_set_intfdata(intf, acecad); usb_set_intfdata(intf, acecad);
...@@ -230,7 +239,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ ...@@ -230,7 +239,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
fail1: input_free_device(input_dev); fail1: input_free_device(input_dev);
kfree(acecad); kfree(acecad);
return -ENOMEM; return err;
} }
static void usb_acecad_disconnect(struct usb_interface *intf) static void usb_acecad_disconnect(struct usb_interface *intf)
......
...@@ -1972,6 +1972,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -1972,6 +1972,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
AIPTEK_PROGRAMMABLE_DELAY_200, AIPTEK_PROGRAMMABLE_DELAY_200,
AIPTEK_PROGRAMMABLE_DELAY_300 AIPTEK_PROGRAMMABLE_DELAY_300
}; };
int err = -ENOMEM;
/* programmableDelay is where the command-line specified /* programmableDelay is where the command-line specified
* delay is kept. We make it the first element of speeds[], * delay is kept. We make it the first element of speeds[],
...@@ -2133,7 +2134,9 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -2133,7 +2134,9 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Register the tablet as an Input Device /* Register the tablet as an Input Device
*/ */
input_register_device(aiptek->inputdev); err = input_register_device(aiptek->inputdev);
if (err)
goto fail2;
/* We now will look for the evdev device which is mapped to /* We now will look for the evdev device which is mapped to
* the tablet. The partial name is kept in the link list of * the tablet. The partial name is kept in the link list of
...@@ -2165,23 +2168,13 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -2165,23 +2168,13 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
return 0; return 0;
fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
aiptek->data_dma); aiptek->data_dma);
fail1: input_free_device(inputdev); fail1: input_free_device(inputdev);
kfree(aiptek); kfree(aiptek);
return -ENOMEM; return err;
} }
/* Forward declaration */
static void aiptek_disconnect(struct usb_interface *intf);
static struct usb_driver aiptek_driver = {
.name = "aiptek",
.probe = aiptek_probe,
.disconnect = aiptek_disconnect,
.id_table = aiptek_ids,
};
/*********************************************************************** /***********************************************************************
* Deal with tablet disconnecting from the system. * Deal with tablet disconnecting from the system.
*/ */
...@@ -2206,6 +2199,13 @@ static void aiptek_disconnect(struct usb_interface *intf) ...@@ -2206,6 +2199,13 @@ static void aiptek_disconnect(struct usb_interface *intf)
} }
} }
static struct usb_driver aiptek_driver = {
.name = "aiptek",
.probe = aiptek_probe,
.disconnect = aiptek_disconnect,
.id_table = aiptek_ids,
};
static int __init aiptek_init(void) static int __init aiptek_init(void)
{ {
int result = usb_register(&aiptek_driver); int result = usb_register(&aiptek_driver);
......
...@@ -491,8 +491,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ...@@ -491,8 +491,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
struct usb_host_interface *iface_desc; struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
int int_in_endpointAddr = 0; int int_in_endpointAddr = 0;
int i, retval = -ENOMEM; int i, error = -ENOMEM;
/* set up the endpoint information */ /* set up the endpoint information */
/* use only the first interrupt-in endpoint */ /* use only the first interrupt-in endpoint */
...@@ -567,17 +566,13 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ...@@ -567,17 +566,13 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
} }
dev->urb = usb_alloc_urb(0, GFP_KERNEL); dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb) { if (!dev->urb)
retval = -ENOMEM;
goto err_free_devs; goto err_free_devs;
}
dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL, dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
&dev->urb->transfer_dma); &dev->urb->transfer_dma);
if (!dev->data) { if (!dev->data)
retval = -ENOMEM;
goto err_free_urb; goto err_free_urb;
}
usb_fill_int_urb(dev->urb, udev, usb_fill_int_urb(dev->urb, udev,
usb_rcvintpipe(udev, int_in_endpointAddr), usb_rcvintpipe(udev, int_in_endpointAddr),
...@@ -633,20 +628,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ...@@ -633,20 +628,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
set_bit(BTN_LEFT, input_dev->keybit); set_bit(BTN_LEFT, input_dev->keybit);
input_register_device(dev->input); error = input_register_device(dev->input);
if (error)
goto err_free_buffer;
/* save our data pointer in this interface device */ /* save our data pointer in this interface device */
usb_set_intfdata(iface, dev); usb_set_intfdata(iface, dev);
return 0; return 0;
err_free_buffer:
usb_buffer_free(dev->udev, dev->datalen,
dev->data, dev->urb->transfer_dma);
err_free_urb: err_free_urb:
usb_free_urb(dev->urb); usb_free_urb(dev->urb);
err_free_devs: err_free_devs:
usb_set_intfdata(iface, NULL); usb_set_intfdata(iface, NULL);
kfree(dev); kfree(dev);
input_free_device(input_dev); input_free_device(input_dev);
return retval; return error;
} }
static void atp_disconnect(struct usb_interface *iface) static void atp_disconnect(struct usb_interface *iface)
......
...@@ -772,15 +772,17 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de ...@@ -772,15 +772,17 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
goto fail3; goto fail3;
/* Set up and register input device */ /* Set up and register input device */
input_register_device(ati_remote->idev); err = input_register_device(ati_remote->idev);
if (err)
goto fail3;
usb_set_intfdata(interface, ati_remote); usb_set_intfdata(interface, ati_remote);
return 0; return 0;
fail3: usb_kill_urb(ati_remote->irq_urb); fail3: usb_kill_urb(ati_remote->irq_urb);
usb_kill_urb(ati_remote->out_urb); usb_kill_urb(ati_remote->out_urb);
fail2: ati_remote_free_buffers(ati_remote); fail2: ati_remote_free_buffers(ati_remote);
fail1: input_free_device(input_dev); fail1: input_free_device(input_dev);
kfree(ati_remote); kfree(ati_remote);
return err; return err;
} }
......
...@@ -337,7 +337,7 @@ static void ati_remote2_complete_key(struct urb *urb) ...@@ -337,7 +337,7 @@ static void ati_remote2_complete_key(struct urb *urb)
static int ati_remote2_input_init(struct ati_remote2 *ar2) static int ati_remote2_input_init(struct ati_remote2 *ar2)
{ {
struct input_dev *idev; struct input_dev *idev;
int i; int i, retval;
idev = input_allocate_device(); idev = input_allocate_device();
if (!idev) if (!idev)
...@@ -364,11 +364,11 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) ...@@ -364,11 +364,11 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
usb_to_input_id(ar2->udev, &idev->id); usb_to_input_id(ar2->udev, &idev->id);
idev->cdev.dev = &ar2->udev->dev; idev->cdev.dev = &ar2->udev->dev;
i = input_register_device(idev); retval = input_register_device(idev);
if (i) if (retval)
input_free_device(idev); input_free_device(idev);
return i; return retval;
} }
static int ati_remote2_urb_init(struct ati_remote2 *ar2) static int ati_remote2_urb_init(struct ati_remote2 *ar2)
......
...@@ -122,6 +122,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -122,6 +122,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
struct kbtab *kbtab; struct kbtab *kbtab;
struct input_dev *input_dev; struct input_dev *input_dev;
int error = -ENOMEM;
kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL); kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
input_dev = input_allocate_device(); input_dev = input_allocate_device();
...@@ -168,15 +169,19 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -168,15 +169,19 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
kbtab->irq->transfer_dma = kbtab->data_dma; kbtab->irq->transfer_dma = kbtab->data_dma;
kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
input_register_device(kbtab->dev); error = input_register_device(kbtab->dev);
if (error)
goto fail3;
usb_set_intfdata(intf, kbtab); usb_set_intfdata(intf, kbtab);
return 0; return 0;
fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); fail3: usb_free_urb(kbtab->irq);
fail1: input_free_device(input_dev); fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
fail1: input_free_device(input_dev);
kfree(kbtab); kfree(kbtab);
return -ENOMEM; return error;
} }
static void kbtab_disconnect(struct usb_interface *intf) static void kbtab_disconnect(struct usb_interface *intf)
......
...@@ -437,7 +437,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic ...@@ -437,7 +437,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
struct usb_keyspan *remote; struct usb_keyspan *remote;
struct input_dev *input_dev; struct input_dev *input_dev;
int i, retval; int i, error;
endpoint = keyspan_get_in_endpoint(interface->cur_altsetting); endpoint = keyspan_get_in_endpoint(interface->cur_altsetting);
if (!endpoint) if (!endpoint)
...@@ -446,7 +446,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic ...@@ -446,7 +446,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote = kzalloc(sizeof(*remote), GFP_KERNEL); remote = kzalloc(sizeof(*remote), GFP_KERNEL);
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!remote || !input_dev) { if (!remote || !input_dev) {
retval = -ENOMEM; error = -ENOMEM;
goto fail1; goto fail1;
} }
...@@ -458,19 +458,19 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic ...@@ -458,19 +458,19 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
if (!remote->in_buffer) { if (!remote->in_buffer) {
retval = -ENOMEM; error = -ENOMEM;
goto fail1; goto fail1;
} }
remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!remote->irq_urb) { if (!remote->irq_urb) {
retval = -ENOMEM; error = -ENOMEM;
goto fail2; goto fail2;
} }
retval = keyspan_setup(udev); error = keyspan_setup(udev);
if (retval) { if (error) {
retval = -ENODEV; error = -ENODEV;
goto fail3; goto fail3;
} }
...@@ -517,7 +517,9 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic ...@@ -517,7 +517,9 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* we can register the device now, as it is ready */ /* we can register the device now, as it is ready */
input_register_device(remote->input); error = input_register_device(remote->input);
if (error)
goto fail3;
/* save our data pointer in this interface device */ /* save our data pointer in this interface device */
usb_set_intfdata(interface, remote); usb_set_intfdata(interface, remote);
...@@ -529,7 +531,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic ...@@ -529,7 +531,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
fail1: kfree(remote); fail1: kfree(remote);
input_free_device(input_dev); input_free_device(input_dev);
return retval; return error;
} }
/* /*
......
...@@ -308,7 +308,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i ...@@ -308,7 +308,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
struct powermate_device *pm; struct powermate_device *pm;
struct input_dev *input_dev; struct input_dev *input_dev;
int pipe, maxp; int pipe, maxp;
int err = -ENOMEM; int error = -ENOMEM;
interface = intf->cur_altsetting; interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc; endpoint = &interface->endpoint[0].desc;
...@@ -387,11 +387,14 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i ...@@ -387,11 +387,14 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
/* register our interrupt URB with the USB system */ /* register our interrupt URB with the USB system */
if (usb_submit_urb(pm->irq, GFP_KERNEL)) { if (usb_submit_urb(pm->irq, GFP_KERNEL)) {
err = -EIO; error = -EIO;
goto fail4; goto fail4;
} }
input_register_device(pm->input); error = input_register_device(pm->input);
if (error)
goto fail5;
/* force an update of everything */ /* force an update of everything */
pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
...@@ -400,12 +403,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i ...@@ -400,12 +403,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
usb_set_intfdata(intf, pm); usb_set_intfdata(intf, pm);
return 0; return 0;
fail4: usb_free_urb(pm->config); fail5: usb_kill_urb(pm->irq);
fail3: usb_free_urb(pm->irq); fail4: usb_free_urb(pm->config);
fail2: powermate_free_buffers(udev, pm); fail3: usb_free_urb(pm->irq);
fail1: input_free_device(input_dev); fail2: powermate_free_buffers(udev, pm);
fail1: input_free_device(input_dev);
kfree(pm); kfree(pm);
return err; return error;
} }
/* Called when a USB device we've accepted ownership of is removed */ /* Called when a USB device we've accepted ownership of is removed */
......
...@@ -201,6 +201,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -201,6 +201,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
struct wacom *wacom; struct wacom *wacom;
struct wacom_wac *wacom_wac; struct wacom_wac *wacom_wac;
struct input_dev *input_dev; struct input_dev *input_dev;
int error = -ENOMEM;
char rep_data[2], limit = 0; char rep_data[2], limit = 0;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
...@@ -252,7 +253,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -252,7 +253,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->irq->transfer_dma = wacom->data_dma; wacom->irq->transfer_dma = wacom->data_dma;
wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
input_register_device(wacom->dev); error = input_register_device(wacom->dev);
if (error)
goto fail3;
/* Ask the tablet to report tablet data. Repeat until it succeeds */ /* Ask the tablet to report tablet data. Repeat until it succeeds */
do { do {
...@@ -265,11 +268,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -265,11 +268,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
usb_set_intfdata(intf, wacom); usb_set_intfdata(intf, wacom);
return 0; return 0;
fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); fail3: usb_free_urb(wacom->irq);
fail1: input_free_device(input_dev); fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
fail1: input_free_device(input_dev);
kfree(wacom); kfree(wacom);
kfree(wacom_wac); kfree(wacom_wac);
return -ENOMEM; return error;
} }
static void wacom_disconnect(struct usb_interface *intf) static void wacom_disconnect(struct usb_interface *intf)
......
...@@ -312,6 +312,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id ...@@ -312,6 +312,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
struct input_dev *input_dev; struct input_dev *input_dev;
struct usb_endpoint_descriptor *ep_irq_in; struct usb_endpoint_descriptor *ep_irq_in;
int i; int i;
int error = -ENOMEM;
for (i = 0; xpad_device[i].idVendor; i++) { for (i = 0; xpad_device[i].idVendor; i++) {
if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
...@@ -373,15 +374,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id ...@@ -373,15 +374,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->irq_in->transfer_dma = xpad->idata_dma; xpad->irq_in->transfer_dma = xpad->idata_dma;
xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
input_register_device(xpad->dev); error = input_register_device(xpad->dev);
if (error)
goto fail3;
usb_set_intfdata(intf, xpad); usb_set_intfdata(intf, xpad);
return 0; return 0;
fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); fail3: usb_free_urb(xpad->irq_in);
fail1: input_free_device(input_dev); fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
fail1: input_free_device(input_dev);
kfree(xpad); kfree(xpad);
return -ENOMEM; return error;
} }
......
...@@ -955,7 +955,9 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -955,7 +955,9 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
} }
} }
input_register_device(yld->idev); ret = input_register_device(yld->idev);
if (ret)
return usb_cleanup(yld, ret);
usb_set_intfdata(intf, yld); usb_set_intfdata(intf, yld);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment