aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi
diff options
context:
space:
mode:
authorBernd Porr <BerndPorr@f2s.com>2008-12-08 18:30:13 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-03 17:53:52 -0400
commit6742c0af2ef2d8ff70e379ebf8a8541190ff44e6 (patch)
tree99a3a654b786b30128ba5a5bb3393b613861cd4d /drivers/staging/comedi
parentc28264dac4348b1514a9a0abcf0014c6b460637f (diff)
Staging: comedi: usbdux[fast] firmware upload changes
usbdux and usbduxfast upload now their firmware via the firmware kernel meachanism. No udev rules are needed for that except the default ones. The firmware will usually be loaded from /lib/firmware. Upload via comedi_config is still possible for static comedi devices (comedi_num_legacy_minors>0). Frank, thanks for the example code which sped up rewriting of the code substantially. From: Bernd Porr <BerndPorr@f2s.com> Cc: Ian Abbott <abbotti@mev.co.uk> Cc: Frank Mori Hess <fmhess@users.sourceforge.net> Cc: David Schleef <ds@schleef.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/comedi')
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c168
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c69
2 files changed, 153 insertions, 84 deletions
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 8aa10c8df67..dc6059b6ca4 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -1,4 +1,4 @@
1#define DRIVER_VERSION "v2.1" 1#define DRIVER_VERSION "v2.2"
2#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" 2#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
3#define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com" 3#define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"
4/* 4/*
@@ -25,8 +25,8 @@ Driver: usbdux
25Description: University of Stirling USB DAQ & INCITE Technology Limited 25Description: University of Stirling USB DAQ & INCITE Technology Limited
26Devices: [ITL] USB-DUX (usbdux.o) 26Devices: [ITL] USB-DUX (usbdux.o)
27Author: Bernd Porr <BerndPorr@f2s.com> 27Author: Bernd Porr <BerndPorr@f2s.com>
28Updated: 25 Nov 2007 28Updated: 8 Dec 2008
29Status: Testing 29Status: Stable
30Configuration options: 30Configuration options:
31 You have to upload firmware with the -i option. The 31 You have to upload firmware with the -i option. The
32 firmware is usually installed under /usr/share/usb or 32 firmware is usually installed under /usr/share/usb or
@@ -79,6 +79,7 @@ sampling rate. If you sample two channels you get 4kHz and so on.
79 * 1.2: added PWM suport via EP4 79 * 1.2: added PWM suport via EP4
80 * 2.0: PWM seems to be stable and is not interfering with the other functions 80 * 2.0: PWM seems to be stable and is not interfering with the other functions
81 * 2.1: changed PWM API 81 * 2.1: changed PWM API
82 * 2.2: added firmware kernel request to fix an udev problem
82 * 83 *
83 */ 84 */
84 85
@@ -94,6 +95,7 @@ sampling rate. If you sample two channels you get 4kHz and so on.
94#include <linux/smp_lock.h> 95#include <linux/smp_lock.h>
95#include <linux/fcntl.h> 96#include <linux/fcntl.h>
96#include <linux/compiler.h> 97#include <linux/compiler.h>
98#include <linux/firmware.h>
97 99
98#include "../comedidev.h" 100#include "../comedidev.h"
99 101
@@ -718,31 +720,29 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub)
718 int errcode = 0; 720 int errcode = 0;
719 uint8_t local_transfer_buffer[16]; 721 uint8_t local_transfer_buffer[16];
720 722
721 if (usbduxsub->probed) { 723 /* 7f92 to zero */
722 /* 7f92 to zero */ 724 local_transfer_buffer[0] = 0;
723 local_transfer_buffer[0] = 0; 725 errcode = usb_control_msg(usbduxsub->usbdev,
724 errcode = usb_control_msg(usbduxsub->usbdev, 726 /* create a pipe for a control transfer */
725 /* create a pipe for a control transfer */ 727 usb_sndctrlpipe(usbduxsub->usbdev, 0),
726 usb_sndctrlpipe(usbduxsub->usbdev, 0), 728 /* bRequest, "Firmware" */
727 /* bRequest, "Firmware" */ 729 USBDUXSUB_FIRMWARE,
728 USBDUXSUB_FIRMWARE, 730 /* bmRequestType */
729 /* bmRequestType */ 731 VENDOR_DIR_OUT,
730 VENDOR_DIR_OUT, 732 /* Value */
731 /* Value */ 733 USBDUXSUB_CPUCS,
732 USBDUXSUB_CPUCS, 734 /* Index */
733 /* Index */ 735 0x0000,
734 0x0000, 736 /* address of the transfer buffer */
735 /* address of the transfer buffer */ 737 local_transfer_buffer,
736 local_transfer_buffer, 738 /* Length */
737 /* Length */ 739 1,
738 1, 740 /* Timeout */
739 /* Timeout */ 741 EZTIMEOUT);
740 EZTIMEOUT); 742 if (errcode < 0) {
741 if (errcode < 0) { 743 dev_err(&usbduxsub->interface->dev,
742 dev_err(&usbduxsub->interface->dev, 744 "comedi_: control msg failed (start)\n");
743 "comedi_: control msg failed (start)\n"); 745 return errcode;
744 return errcode;
745 }
746 } 746 }
747 return 0; 747 return 0;
748} 748}
@@ -752,28 +752,27 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub)
752 int errcode = 0; 752 int errcode = 0;
753 753
754 uint8_t local_transfer_buffer[16]; 754 uint8_t local_transfer_buffer[16];
755 if (usbduxsub->probed) { 755
756 /* 7f92 to one */ 756 /* 7f92 to one */
757 local_transfer_buffer[0] = 1; 757 local_transfer_buffer[0] = 1;
758 errcode = usb_control_msg(usbduxsub->usbdev, 758 errcode = usb_control_msg(usbduxsub->usbdev,
759 usb_sndctrlpipe(usbduxsub->usbdev, 0), 759 usb_sndctrlpipe(usbduxsub->usbdev, 0),
760 /* bRequest, "Firmware" */ 760 /* bRequest, "Firmware" */
761 USBDUXSUB_FIRMWARE, 761 USBDUXSUB_FIRMWARE,
762 /* bmRequestType */ 762 /* bmRequestType */
763 VENDOR_DIR_OUT, 763 VENDOR_DIR_OUT,
764 /* Value */ 764 /* Value */
765 USBDUXSUB_CPUCS, 765 USBDUXSUB_CPUCS,
766 /* Index */ 766 /* Index */
767 0x0000, local_transfer_buffer, 767 0x0000, local_transfer_buffer,
768 /* Length */ 768 /* Length */
769 1, 769 1,
770 /* Timeout */ 770 /* Timeout */
771 EZTIMEOUT); 771 EZTIMEOUT);
772 if (errcode < 0) { 772 if (errcode < 0) {
773 dev_err(&usbduxsub->interface->dev, 773 dev_err(&usbduxsub->interface->dev,
774 "comedi_: control msg failed (stop)\n"); 774 "comedi_: control msg failed (stop)\n");
775 return errcode; 775 return errcode;
776 }
777 } 776 }
778 return 0; 777 return 0;
779} 778}
@@ -784,13 +783,7 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub,
784{ 783{
785 int errcode; 784 int errcode;
786 785
787 if (usbduxsub->probed) { 786 errcode = usb_control_msg(usbduxsub->usbdev,
788 dev_dbg(&usbduxsub->interface->dev,
789 "comedi%d: usbdux: uploading %d bytes"
790 " to addr %d, first byte=%d.\n",
791 usbduxsub->comedidev->minor, len,
792 startAddr, local_transfer_buffer[0]);
793 errcode = usb_control_msg(usbduxsub->usbdev,
794 usb_sndctrlpipe(usbduxsub->usbdev, 0), 787 usb_sndctrlpipe(usbduxsub->usbdev, 0),
795 /* brequest, firmware */ 788 /* brequest, firmware */
796 USBDUXSUB_FIRMWARE, 789 USBDUXSUB_FIRMWARE,
@@ -806,16 +799,12 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub,
806 len, 799 len,
807 /* timeout */ 800 /* timeout */
808 EZTIMEOUT); 801 EZTIMEOUT);
809 dev_dbg(&usbduxsub->interface->dev, 802 dev_dbg(&usbduxsub->interface->dev,
810 "comedi_: result=%d\n", errcode); 803 "comedi_: result=%d\n", errcode);
811 if (errcode < 0) { 804 if (errcode < 0) {
812 dev_err(&usbduxsub->interface->dev, 805 dev_err(&usbduxsub->interface->dev,
813 "comedi_: upload failed\n"); 806 "comedi_: upload failed\n");
814 return errcode; 807 return errcode;
815 }
816 } else {
817 /* no device on the bus for this index */
818 return -EFAULT;
819 } 808 }
820 return 0; 809 return 0;
821} 810}
@@ -2292,7 +2281,7 @@ static unsigned hex2unsigned(char *h)
2292#define FIRMWARE_MAX_LEN 0x2000 2281#define FIRMWARE_MAX_LEN 0x2000
2293 2282
2294/* taken from David Brownell's fxload and adjusted for this driver */ 2283/* taken from David Brownell's fxload and adjusted for this driver */
2295static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr, 2284static int read_firmware(struct usbduxsub *usbduxsub, const void *firmwarePtr,
2296 long size) 2285 long size)
2297{ 2286{
2298 struct device *dev = &usbduxsub->interface->dev; 2287 struct device *dev = &usbduxsub->interface->dev;
@@ -2399,6 +2388,34 @@ static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr,
2399 return res; 2388 return res;
2400} 2389}
2401 2390
2391static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
2392 void *context)
2393{
2394 struct usbduxsub *usbduxsub_tmp = context;
2395 struct usb_device *usbdev = usbduxsub_tmp->usbdev;
2396 int ret;
2397
2398 if (fw == NULL) {
2399 dev_err(&usbdev->dev,
2400 "Firmware complete handler without firmware!\n");
2401 return;
2402 }
2403
2404 /*
2405 * we need to upload the firmware here because fw will be
2406 * freed once we've left this function
2407 */
2408 ret = read_firmware(usbduxsub_tmp, fw->data, fw->size);
2409
2410 if (ret) {
2411 dev_err(&usbdev->dev,
2412 "Could not upload firmware (err=%d)\n",
2413 ret);
2414 return;
2415 }
2416 comedi_usb_auto_config(usbdev, BOARDNAME);
2417}
2418
2402/* allocate memory for the urbs and initialise them */ 2419/* allocate memory for the urbs and initialise them */
2403static int usbduxsub_probe(struct usb_interface *uinterf, 2420static int usbduxsub_probe(struct usb_interface *uinterf,
2404 const struct usb_device_id *id) 2421 const struct usb_device_id *id)
@@ -2407,6 +2424,7 @@ static int usbduxsub_probe(struct usb_interface *uinterf,
2407 struct device *dev = &uinterf->dev; 2424 struct device *dev = &uinterf->dev;
2408 int i; 2425 int i;
2409 int index; 2426 int index;
2427 int ret;
2410 2428
2411 dev_dbg(dev, "comedi_: usbdux_: " 2429 dev_dbg(dev, "comedi_: usbdux_: "
2412 "finding a free structure for the usb-device\n"); 2430 "finding a free structure for the usb-device\n");
@@ -2641,6 +2659,19 @@ static int usbduxsub_probe(struct usb_interface *uinterf,
2641 /* we've reached the bottom of the function */ 2659 /* we've reached the bottom of the function */
2642 usbduxsub[index].probed = 1; 2660 usbduxsub[index].probed = 1;
2643 up(&start_stop_sem); 2661 up(&start_stop_sem);
2662
2663 ret = request_firmware_nowait(THIS_MODULE,
2664 FW_ACTION_HOTPLUG,
2665 "usbdux_firmware.hex",
2666 &udev->dev,
2667 usbduxsub + index,
2668 usbdux_firmware_request_complete_handler);
2669
2670 if (ret) {
2671 dev_err(dev, "Could not load firmware (err=%d)\n", ret);
2672 return ret;
2673 }
2674
2644 dev_info(dev, "comedi_: usbdux%d " 2675 dev_info(dev, "comedi_: usbdux%d "
2645 "has been successfully initialised.\n", index); 2676 "has been successfully initialised.\n", index);
2646 /* success */ 2677 /* success */
@@ -2662,6 +2693,7 @@ static void usbduxsub_disconnect(struct usb_interface *intf)
2662 "comedi_: BUG! called with wrong ptr!!!\n"); 2693 "comedi_: BUG! called with wrong ptr!!!\n");
2663 return; 2694 return;
2664 } 2695 }
2696 comedi_usb_auto_unconfig(udev);
2665 down(&start_stop_sem); 2697 down(&start_stop_sem);
2666 down(&usbduxsub_tmp->sem); 2698 down(&usbduxsub_tmp->sem);
2667 tidy_up(usbduxsub_tmp); 2699 tidy_up(usbduxsub_tmp);
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 625dde7e198..b1a7cbec731 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -33,9 +33,12 @@
33 * 1MHz/16ch=62.5kHz 33 * 1MHz/16ch=62.5kHz
34 * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks! 34 * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks!
35 * 0.99a: added external trigger. 35 * 0.99a: added external trigger.
36 * 1.00: added firmware kernel request to the driver which fixed
37 * udev coldplug problem
36 */ 38 */
37 39
38#include <linux/kernel.h> 40#include <linux/kernel.h>
41#include <linux/firmware.h>
39#include <linux/module.h> 42#include <linux/module.h>
40#include <linux/init.h> 43#include <linux/init.h>
41#include <linux/slab.h> 44#include <linux/slab.h>
@@ -48,7 +51,7 @@
48#include "../comedidev.h" 51#include "../comedidev.h"
49 52
50 53
51#define DRIVER_VERSION "v0.99a" 54#define DRIVER_VERSION "v1.0"
52#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" 55#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
53#define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com" 56#define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com"
54#define BOARDNAME "usbduxfast" 57#define BOARDNAME "usbduxfast"
@@ -444,9 +447,6 @@ static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
444 int ret; 447 int ret;
445 unsigned char local_transfer_buffer[16]; 448 unsigned char local_transfer_buffer[16];
446 449
447 if (!udfs->probed)
448 return 0;
449
450 /* 7f92 to zero */ 450 /* 7f92 to zero */
451 local_transfer_buffer[0] = 0; 451 local_transfer_buffer[0] = 0;
452 ret = usb_control_msg(udfs->usbdev, 452 ret = usb_control_msg(udfs->usbdev,
@@ -471,9 +471,6 @@ static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
471 int ret; 471 int ret;
472 unsigned char local_transfer_buffer[16]; 472 unsigned char local_transfer_buffer[16];
473 473
474 if (!udfs->probed)
475 return 0;
476
477 /* 7f92 to one */ 474 /* 7f92 to one */
478 local_transfer_buffer[0] = 1; 475 local_transfer_buffer[0] = 1;
479 ret = usb_control_msg(udfs->usbdev, 476 ret = usb_control_msg(udfs->usbdev,
@@ -500,10 +497,6 @@ static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs,
500{ 497{
501 int ret; 498 int ret;
502 499
503 if (!udfs->probed)
504 /* no device on the bus for this index */
505 return -EFAULT;
506
507#ifdef CONFIG_COMEDI_DEBUG 500#ifdef CONFIG_COMEDI_DEBUG
508 printk(KERN_DEBUG "comedi%d: usbduxfast: uploading %d bytes", 501 printk(KERN_DEBUG "comedi%d: usbduxfast: uploading %d bytes",
509 udfs->comedidev->minor, len); 502 udfs->comedidev->minor, len);
@@ -1396,8 +1389,8 @@ static unsigned hex2unsigned(char *h)
1396/* 1389/*
1397 * taken from David Brownell's fxload and adjusted for this driver 1390 * taken from David Brownell's fxload and adjusted for this driver
1398 */ 1391 */
1399static int read_firmware(struct usbduxfastsub_s *udfs, void *firmwarePtr, 1392static int read_firmware(struct usbduxfastsub_s *udfs, const void *firmwarePtr,
1400 long size) 1393 long size)
1401{ 1394{
1402 int i = 0; 1395 int i = 0;
1403 unsigned char *fp = (char *)firmwarePtr; 1396 unsigned char *fp = (char *)firmwarePtr;
@@ -1538,6 +1531,32 @@ static void tidy_up(struct usbduxfastsub_s *udfs)
1538 udfs->ai_cmd_running = 0; 1531 udfs->ai_cmd_running = 0;
1539} 1532}
1540 1533
1534static void usbduxfast_firmware_request_complete_handler(const struct firmware *fw,
1535 void *context)
1536{
1537 struct usbduxfastsub_s *usbduxfastsub_tmp = context;
1538 struct usb_device *usbdev = usbduxfastsub_tmp->usbdev;
1539 int ret;
1540
1541 if (fw == NULL)
1542 return;
1543
1544 /*
1545 * we need to upload the firmware here because fw will be
1546 * freed once we've left this function
1547 */
1548 ret = read_firmware(usbduxfastsub_tmp, fw->data, fw->size);
1549
1550 if (ret) {
1551 dev_err(&usbdev->dev,
1552 "Could not upload firmware (err=%d)\n",
1553 ret);
1554 return;
1555 }
1556
1557 comedi_usb_auto_config(usbdev, BOARDNAME);
1558}
1559
1541/* 1560/*
1542 * allocate memory for the urbs and initialise them 1561 * allocate memory for the urbs and initialise them
1543 */ 1562 */
@@ -1547,6 +1566,7 @@ static int usbduxfastsub_probe(struct usb_interface *uinterf,
1547 struct usb_device *udev = interface_to_usbdev(uinterf); 1566 struct usb_device *udev = interface_to_usbdev(uinterf);
1548 int i; 1567 int i;
1549 int index; 1568 int index;
1569 int ret;
1550 1570
1551 if (udev->speed != USB_SPEED_HIGH) { 1571 if (udev->speed != USB_SPEED_HIGH) {
1552 printk(KERN_ERR "comedi_: usbduxfast_: This driver needs" 1572 printk(KERN_ERR "comedi_: usbduxfast_: This driver needs"
@@ -1644,6 +1664,20 @@ static int usbduxfastsub_probe(struct usb_interface *uinterf,
1644 /* we've reached the bottom of the function */ 1664 /* we've reached the bottom of the function */
1645 usbduxfastsub[index].probed = 1; 1665 usbduxfastsub[index].probed = 1;
1646 up(&start_stop_sem); 1666 up(&start_stop_sem);
1667
1668 ret = request_firmware_nowait(THIS_MODULE,
1669 FW_ACTION_HOTPLUG,
1670 "usbduxfast_firmware.hex",
1671 &udev->dev,
1672 usbduxfastsub + index,
1673 usbduxfast_firmware_request_complete_handler);
1674
1675 if (ret) {
1676 dev_err(&udev->dev, "could not load firmware (err=%d)\n",
1677 ret);
1678 return ret;
1679 }
1680
1647 printk(KERN_INFO "comedi_: usbduxfast%d has been successfully " 1681 printk(KERN_INFO "comedi_: usbduxfast%d has been successfully "
1648 "initialized.\n", index); 1682 "initialized.\n", index);
1649 /* success */ 1683 /* success */
@@ -1665,6 +1699,9 @@ static void usbduxfastsub_disconnect(struct usb_interface *intf)
1665 "ptr!!!\n"); 1699 "ptr!!!\n");
1666 return; 1700 return;
1667 } 1701 }
1702
1703 comedi_usb_auto_unconfig(udev);
1704
1668 down(&start_stop_sem); 1705 down(&start_stop_sem);
1669 down(&udfs->sem); 1706 down(&udfs->sem);
1670 tidy_up(udfs); 1707 tidy_up(udfs);
@@ -1714,10 +1751,10 @@ static int usbduxfast_attach(comedi_device *dev, comedi_devconfig *it)
1714 1751
1715 /* trying to upload the firmware into the chip */ 1752 /* trying to upload the firmware into the chip */
1716 if (comedi_aux_data(it->options, 0) && 1753 if (comedi_aux_data(it->options, 0) &&
1717 it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { 1754 it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
1718 read_firmware(&usbduxfastsub[index], 1755 read_firmware(&usbduxfastsub[index],
1719 comedi_aux_data(it->options, 0), 1756 comedi_aux_data(it->options, 0),
1720 it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]); 1757 it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
1721 } 1758 }
1722 1759
1723 dev->board_name = BOARDNAME; 1760 dev->board_name = BOARDNAME;