Hello,
I am in the middle of writing a driver for the Cypress M8. This is a
way-too-goofy USB to serial converter.
I have a fairly clear understanding of what I need to do to make it work,
but here is where I run into issues...

The device is a 'USB to serial converter' but it is in the HID class...
According to its documentation, it has three endpoints.
0 For reading or writing the serial parameters. (Feature report)
1 For reading data from the serial port (Input report)
2 For writing data to the serial port (Output report)

Do I put the driver in the input directory and use the hid-core functions,
or do I put it in the serial directory and use the usb-serial functions?

At the time being, I have it in the serial directory and I am using the
usb-serial functions. I added a few lines of code to the hid-core.c file
to get it to ignore the device.

At this point all is well, and my driver in the serial directory picks it
up and registers the serial device.. The way I understand the USB
specification, you can use the interrupt_in_pipe for reading input reports
and the interrupt_out_pipe for writing output reports However,
usb-serial.c is missing the functions to do interrupt out transfers.. So,
off I went and added them...
(I included the diffs below...) I am not sure if this is correct however..
Is there a reason that there is on support for interrupt out transfers in
the usb-serial?

I am now able to read and decode the data from endpoint 1, and I can
send data to the serial port via endpoint 2, but here is
where I really get stuck and the main reason I am writing to you..

In usb-serial.c the iface_desc->desc.bNumEndpoints shows up as 2, not 3...
I am working on the following assumptions any of which are likely to be
wrong...

Ok, so endpoint 0 is a control endpoint and it doesn't show up on the
list... So I need to use a function like usb_control_msg() to talk to it.
If so, I need to construct a feature report and send it off which means
that I need some #defines from ../input/hid.h (which seems a messy way of
doing things to me) and I need something like...
---------------------------------------------------------------------------
// The feature report needs to be 5 bytes
// For now I am sending a test feature report to put the device in a known
// sane state (9600 baud, no parity, one stop bit 8 bits (8N1))
__u8 feature[5]={
        0x80,
        0x25,
        0x00,
        0x00,
        0x03
};

usb_control_msg (port->serial->dev, usb_sndctrlpipe (port->serial->dev, 0),
                HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
                0x0300, 0, feature, 5, 500);
---------------------------------------------------------------------------
The above call is always failing.. I am not sure if I have everything the
way that I need it or not, the USB documentation is unclear to me if the
actual data needs to be in some sort of a packet or not.. Are there any
examples of sending a feature report to a device? Should I really be using
the hid-core stuff instead?
This will be my first (of hopefully many to come) contributions to the
Linux kernel...
If I am on the right track with the patches and the driver, what do I need
to do to get them to the right people to be included in the kernel?


Thanks in advance for your help,
-Neil Whelchel-
First Light Internet Services
760 366-0145
- We don't do Window$, that's what the janitor is for -

Bubble Memory, n.:
        A derogatory term, usually referring to a person's
intelligence.  See also "vacuum tube".

---------------------------------------------------------------------------

---------------------------------------------------------------------------


diff -rc linux-2.6.0-test5.dist/drivers/usb/input/hid-core.c 
linux-2.6.0-test5/drivers/usb/input/hid-core.c
*** linux-2.6.0-test5.dist/drivers/usb/input/hid-core.c Mon Sep  8 12:50:07 2003
--- linux-2.6.0-test5/drivers/usb/input/hid-core.c      Sat Sep 20 23:51:00 2003
***************
*** 1354,1359 ****
--- 1354,1362 ----
  #define USB_VENDOR_ID_A4TECH          0x09DA
  #define USB_DEVICE_ID_A4TECH_WCP32PU  0x0006

+ #define USB_VENDOR_ID_CYPRESS         0x1163
+ #define USB_DEVICE_ID_CYPRESS_M8      0x0100
+
  struct hid_blacklist {
        __u16 idVendor;
        __u16 idProduct;
***************
*** 1403,1408 ****
--- 1406,1412 ----
        { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, 
HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, 
HID_QUIRK_2WHEEL_MOUSE_HACK },
+       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_M8, HID_QUIRK_IGNORE },
        { 0, 0 }
  };

diff -rc linux-2.6.0-test5.dist/drivers/usb/serial/Kconfig 
linux-2.6.0-test5/drivers/usb/serial/Kconfig
*** linux-2.6.0-test5.dist/drivers/usb/serial/Kconfig   Mon Sep  8 12:50:18 2003
--- linux-2.6.0-test5/drivers/usb/serial/Kconfig        Sat Sep 20 22:21:06 2003
***************
*** 75,80 ****
--- 75,94 ----
          The module will be called belkin_sa.  If you want to compile it as
          a module, say M here and read <file:Documentation/modules.txt>.

+ config USB_SERIAL_CYPRESS
+       tristate "USB Cypress serial converter"
+       depends on USB_SERIAL
+       help
+         Say Y here if you want to use a device that contains the Cypress
+         USB to serial converter such as the DeLORME Earthmate GPS
+         For some reason this device was put in the HID class even though
+         its only function is a serial converter.
+
+         This code is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         The module will be called whiteheat.  If you want to compile it as
+         a module, say M here and read <file:Documentation/modules.txt>.
+
  config USB_SERIAL_WHITEHEAT
        tristate "USB ConnectTech WhiteHEAT Serial Driver"
        depends on USB_SERIAL
diff -rc linux-2.6.0-test5.dist/drivers/usb/serial/Makefile 
linux-2.6.0-test5/drivers/usb/serial/Makefile
*** linux-2.6.0-test5.dist/drivers/usb/serial/Makefile  Mon Sep  8 12:49:54 2003
--- linux-2.6.0-test5/drivers/usb/serial/Makefile       Sat Sep 20 22:21:55 2003
***************
*** 11,16 ****
--- 11,17 ----

  obj-$(CONFIG_USB_SERIAL_VISOR)                        += visor.o
  obj-$(CONFIG_USB_SERIAL_IPAQ)                 += ipaq.o
+ obj-$(CONFIG_USB_SERIAL_CYPRESS)              += cypress.o
  obj-$(CONFIG_USB_SERIAL_WHITEHEAT)            += whiteheat.o
  obj-$(CONFIG_USB_SERIAL_FTDI_SIO)             += ftdi_sio.o
  obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)          += keyspan_pda.o
diff -rc linux-2.6.0-test5.dist/drivers/usb/serial/usb-serial.c
linux-2.6.0-test5/drivers/usb/serial/usb-serial.c
*** linux-2.6.0-test5.dist/drivers/usb/serial/usb-serial.c      Mon Sep  8 12:50:02 
2003
--- linux-2.6.0-test5/drivers/usb/serial/usb-serial.c   Sun Sep 21 22:31:03 2003
***************
*** 894,902 ****
--- 894,907 ----
                                usb_unlink_urb(port->interrupt_in_urb);
                                usb_free_urb(port->interrupt_in_urb);
                        }
+                       if (port->interrupt_out_urb) {
+                               usb_unlink_urb(port->interrupt_out_urb);
+                               usb_free_urb(port->interrupt_out_urb);
+                       }
                        kfree(port->bulk_in_buffer);
                        kfree(port->bulk_out_buffer);
                        kfree(port->interrupt_in_buffer);
+                       kfree(port->interrupt_out_buffer);
                }
        }

***************
*** 927,935 ****
--- 932,945 ----
                usb_unlink_urb(port->interrupt_in_urb);
                usb_free_urb(port->interrupt_in_urb);
        }
+       if (port->interrupt_out_urb) {
+               usb_unlink_urb(port->interrupt_out_urb);
+               usb_free_urb(port->interrupt_out_urb);
+       }
        kfree(port->bulk_in_buffer);
        kfree(port->bulk_out_buffer);
        kfree(port->interrupt_in_buffer);
+       kfree(port->interrupt_out_buffer);
        kfree(port);
  }

***************
*** 967,972 ****
--- 977,983 ----
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
        struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
+       struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
        struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
        struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
        struct usb_serial_device_type *type = NULL;
***************
*** 977,982 ****
--- 988,994 ----
        int buffer_size;
        int i;
        int num_interrupt_in = 0;
+       int num_interrupt_out = 0;
        int num_bulk_in = 0;
        int num_bulk_out = 0;
        int num_ports = 0;
***************
*** 1026,1039 ****

        /* descriptor matches, let's find the endpoints needed */
        /* check out the endpoints */
        iface_desc = &interface->altsetting[0];
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;

                if ((endpoint->bEndpointAddress & 0x80) &&
                    ((endpoint->bmAttributes & 3) == 0x02)) {
                        /* we found a bulk in endpoint */
!                       dbg("found bulk in");
                        bulk_in_endpoint[num_bulk_in] = endpoint;
                        ++num_bulk_in;
                }
--- 1038,1053 ----

        /* descriptor matches, let's find the endpoints needed */
        /* check out the endpoints */
+       dbg("checking for endpoints");
        iface_desc = &interface->altsetting[0];
+       dbg("this device claims to have %d endpoints",iface_desc->desc.bNumEndpoints);
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;

                if ((endpoint->bEndpointAddress & 0x80) &&
                    ((endpoint->bmAttributes & 3) == 0x02)) {
                        /* we found a bulk in endpoint */
!                       dbg("found bulk in on endpoint %d",i);
                        bulk_in_endpoint[num_bulk_in] = endpoint;
                        ++num_bulk_in;
                }
***************
*** 1041,1047 ****
                if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
                    ((endpoint->bmAttributes & 3) == 0x02)) {
                        /* we found a bulk out endpoint */
!                       dbg("found bulk out");
                        bulk_out_endpoint[num_bulk_out] = endpoint;
                        ++num_bulk_out;
                }
--- 1055,1061 ----
                if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
                    ((endpoint->bmAttributes & 3) == 0x02)) {
                        /* we found a bulk out endpoint */
!                       dbg("found bulk out on endpoint %d",i);
                        bulk_out_endpoint[num_bulk_out] = endpoint;
                        ++num_bulk_out;
                }
***************
*** 1049,1060 ****
                if ((endpoint->bEndpointAddress & 0x80) &&
                    ((endpoint->bmAttributes & 3) == 0x03)) {
                        /* we found a interrupt in endpoint */
!                       dbg("found interrupt in");
                        interrupt_in_endpoint[num_interrupt_in] = endpoint;
                        ++num_interrupt_in;
                }
        }
!
  #if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
        /* BEGIN HORRIBLE HACK FOR PL2303 */
        /* this is needed due to the looney way its endpoints are set up */
--- 1063,1081 ----
                if ((endpoint->bEndpointAddress & 0x80) &&
                    ((endpoint->bmAttributes & 3) == 0x03)) {
                        /* we found a interrupt in endpoint */
!                       dbg("found interrupt in on endpoint %d",i);
                        interrupt_in_endpoint[num_interrupt_in] = endpoint;
                        ++num_interrupt_in;
                }
+               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+                   ((endpoint->bmAttributes & 3) == 0x03)) {
+                       /* we found a interrupt out endpoint */
+                       dbg("found interrupt out on endpoint %d",i);
+                       interrupt_out_endpoint[num_interrupt_out] = endpoint;
+                       ++num_interrupt_out;
+               }
        }
!       dbg("found %d bulk_in, %d bulk_out, %d interrupt_in %d interrupt_out", 
num_bulk_in, num_bulk_out, num_interrupt_in, num_interrupt_out);
  #if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
        /* BEGIN HORRIBLE HACK FOR PL2303 */
        /* this is needed due to the looney way its endpoints are set up */
***************
*** 1129,1139 ****
--- 1150,1162 ----
        serial->num_bulk_in = num_bulk_in;
        serial->num_bulk_out = num_bulk_out;
        serial->num_interrupt_in = num_interrupt_in;
+       serial->num_interrupt_out = num_interrupt_out;

        /* create our ports, we need as many as the max endpoints */
        /* we don't use num_ports here cauz some devices have more endpoint pairs than 
ports */
        max_endpoints = max(num_bulk_in, num_bulk_out);
        max_endpoints = max(max_endpoints, num_interrupt_in);
+       max_endpoints = max(max_endpoints, num_interrupt_out);
        max_endpoints = max(max_endpoints, (int)serial->num_ports);
        serial->num_port_pointers = max_endpoints;
        dbg("%s - setting up %d port structures for this device", __FUNCTION__, 
max_endpoints);
***************
*** 1220,1225 ****
--- 1243,1274 ----
                                  endpoint->bInterval);
        }

+       for (i = 0; i < num_interrupt_out; ++i) {
+               endpoint = interrupt_out_endpoint[i];
+               port = serial->port[i];
+               port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!port->interrupt_out_urb) {
+                       dev_err(&interface->dev, "No free urbs available\n");
+                       goto probe_error;
+               }
+               buffer_size = endpoint->wMaxPacketSize;
+               port->interrupt_out_size = buffer_size;
+               port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
+               port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
+               if (!port->interrupt_out_buffer) {
+                       dev_err(&interface->dev, "Couldn't allocate 
interrupt_out_buffer\n");
+                       goto probe_error;
+               }
+               usb_fill_int_urb (port->interrupt_out_urb, dev,
+                                  usb_sndintpipe (dev,
+                                                   endpoint->bEndpointAddress),
+                                  port->interrupt_out_buffer, buffer_size,
+                                  serial->type->write_int_callback, port,
+                                  endpoint->bInterval);
+       }
+
+
+
        /* if this device type has an attach function, call it */
        if (type->attach) {
                if (!try_module_get(type->owner)) {
***************
*** 1281,1286 ****
--- 1330,1343 ----
                if (port->interrupt_in_urb)
                        usb_free_urb (port->interrupt_in_urb);
                kfree(port->interrupt_in_buffer);
+       }
+       for (i = 0; i < num_interrupt_out; ++i) {
+               port = serial->port[i];
+               if (!port)
+                       continue;
+               if (port->interrupt_out_urb)
+                       usb_free_urb (port->interrupt_out_urb);
+               kfree(port->interrupt_out_buffer);
        }

        /* return the minor range that this device had */
diff -rc linux-2.6.0-test5.dist/drivers/usb/serial/usb-serial.h
linux-2.6.0-test5/drivers/usb/serial/usb-serial.h
*** linux-2.6.0-test5.dist/drivers/usb/serial/usb-serial.h      Mon Sep  8 12:51:01 
2003
--- linux-2.6.0-test5/drivers/usb/serial/usb-serial.h   Sun Sep 21 18:44:28 2003
***************
*** 77,82 ****
--- 77,84 ----
   * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
   * @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe
   *    for this port.
+  * @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe
+  *    for this port.
   * @bulk_in_buffer: pointer to the bulk in buffer for this port.
   * @read_urb: pointer to the bulk in struct urb for this port.
   * @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this
***************
*** 103,108 ****
--- 105,115 ----
        struct urb *            interrupt_in_urb;
        __u8                    interrupt_in_endpointAddress;

+       unsigned char *         interrupt_out_buffer;
+       int                     interrupt_out_size;
+       struct urb *            interrupt_out_urb;
+       __u8                    interrupt_out_endpointAddress;
+
        unsigned char *         bulk_in_buffer;
        struct urb *            read_urb;
        __u8                    bulk_in_endpointAddress;
***************
*** 139,144 ****
--- 146,152 ----
   * @minor: the starting minor number for this device
   * @num_ports: the number of ports this device has
   * @num_interrupt_in: number of interrupt in endpoints we have
+  * @num_interrupt_out: number of interrupt out endpoints we have
   * @num_bulk_in: number of bulk in endpoints we have
   * @num_bulk_out: number of bulk out endpoints we have
   * @vendor: vendor id of this device
***************
*** 158,163 ****
--- 166,172 ----
        unsigned char                   num_ports;
        unsigned char                   num_port_pointers;
        char                            num_interrupt_in;
+       char                            num_interrupt_out;
        char                            num_bulk_in;
        char                            num_bulk_out;
        __u16                           vendor;
***************
*** 193,198 ****
--- 202,209 ----
   *    of the devices this structure can support.
   * @num_interrupt_in: the number of interrupt in endpoints this device will
   *    have.
+  * @num_interrupt_out: the number of interrupt out endpoints this device will
+  *    have.
   * @num_bulk_in: the number of bulk in endpoints this device will have.
   * @num_bulk_out: the number of bulk out endpoints this device will have.
   * @num_ports: the number of different ports this device will have.
***************
*** 225,230 ****
--- 236,242 ----
        char    *short_name;
        const struct usb_device_id *id_table;
        char    num_interrupt_in;
+       char    num_interrupt_out;
        char    num_bulk_in;
        char    num_bulk_out;
        char    num_ports;
***************
*** 256,261 ****
--- 268,274 ----
        int  (*tiocmset)        (struct usb_serial_port *port, struct file *file, 
unsigned int set, unsigned int clear);

        void (*read_int_callback)(struct urb *urb, struct pt_regs *regs);
+       void (*write_int_callback)(struct urb *urb, struct pt_regs *regs);
        void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
        void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
  };






-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to