Fix sending data with prolific devices. Seems they weren't initialised correctly. We now send the same stuff Linux does (without telling why), and it seems to work.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20493 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol
2007-04-01 11:51:32 +00:00
parent 0786dcba41
commit 694e5de9b0
2 changed files with 78 additions and 4 deletions
@@ -133,6 +133,7 @@ struct _s_usb_serial_device{
struct _spec_acm{ /* ACM-compatible devices */
}acm;
struct _spec_prolific{ /* Prolific devices*/
bool is_HX; /* Linux handles HX type differently */
}prolific;
struct _spec_ftdi{ /* FTDI devices*/
uint8 hdrlen;
@@ -18,18 +18,30 @@ status_t add_prolific_device(usb_serial_device *usd,
struct usb_endpoint_info *comm_epi = NULL;
struct usb_endpoint_info *data_out_epi = NULL;
struct usb_endpoint_info *data_in_epi = NULL;
const usb_device_descriptor *ddesc;
status_t status = ENODEV;
int i = 0;
TRACE_FUNCALLS("> add_prolific_device(%08x, %08x)\n", usd, uci);
/* check for device type.
* Linux checks for type 0, 1 and HX, but handles 0 and 1 the same.
* We'll just check for HX then.
*/
if ((ddesc = (*usb_m->get_device_descriptor)(usd->dev))){
usd->spec.prolific.is_HX = (ddesc->device_class != 0x02 &&
ddesc->max_packet_size_0 == 0x40);
}
if(uci->interface_count){
struct usb_interface_info *uii = uci->interface[0].active;
for(i = 0; i < uii->endpoint_count; i++){
if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_INTERRUPT){
if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN)
== USB_EP_ADDR_DIR_IN) /*USB_EP_ADDR_DIR_OUT = 0x0*/
== USB_EP_ADDR_DIR_IN /*USB_EP_ADDR_DIR_OUT = 0x0*/){
TRACE("add_prolific_device:comm endpoint at %d\n", i);
comm_epi = &uii->endpoint[i];
}
}
}
/*They say that USB-RSAQ1 has 2 interfaces */
@@ -41,10 +53,12 @@ status_t add_prolific_device(usb_serial_device *usd,
if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_BULK){
if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN)
== USB_EP_ADDR_DIR_IN){
TRACE("add_prolific_device:in endpoint at %d\n", i);
data_in_epi = &uii->endpoint[i];
}else{
if(uii->endpoint[i].descr->endpoint_address
/*USB_EP_ADDR_DIR_OUT = 0x0*/){
if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN)
== USB_EP_ADDR_DIR_OUT){
TRACE("add_prolific_device:out endpoint at %d\n", i);
data_out_epi = &uii->endpoint[i];
}
}
@@ -63,13 +77,72 @@ status_t add_prolific_device(usb_serial_device *usd,
return status;
}
struct req_item {
uint8 requestType;
uint8 request;
uint16 value;
uint16 index;
};
#define PLRT_O (USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT)
#define PLRT_I (USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN)
/* Linux sends all those, and it seems to work for me */
/* see drivers/usb/serial/pl2303.c */
static struct req_item pl_reset_common_reqs[] = {
{PLRT_I, PROLIFIC_SET_REQUEST, 0x8484, 0},
{PLRT_O, PROLIFIC_SET_REQUEST, 0x0404, 0},
{PLRT_I, PROLIFIC_SET_REQUEST, 0x8484, 0},
{PLRT_I, PROLIFIC_SET_REQUEST, 0x8383, 0},
{PLRT_I, PROLIFIC_SET_REQUEST, 0x8484, 0},
{PLRT_O, PROLIFIC_SET_REQUEST, 0x0404, 1},
{PLRT_I, PROLIFIC_SET_REQUEST, 0x8484, 0},
{PLRT_I, PROLIFIC_SET_REQUEST, 0x8383, 0},
{PLRT_O, PROLIFIC_SET_REQUEST, 0x0000, 1},
{PLRT_O, PROLIFIC_SET_REQUEST, 0x0001, 0}
};
static struct req_item pl_reset_common_hx[] = {
{PLRT_O, PROLIFIC_SET_REQUEST, 2, 0x44},
{PLRT_O, PROLIFIC_SET_REQUEST, 8, 0},
{PLRT_O, PROLIFIC_SET_REQUEST, 0, 0}
};
static struct req_item pl_reset_common_nhx[] = {
{PLRT_O, PROLIFIC_SET_REQUEST, 2, 0x24}
};
static status_t usb_send_requ_list(const usb_device *dev, struct req_item *list, size_t len){
char buf[10];
int i;
status_t status;
for (i = 0; i < len; i++){
bool o = (list[i].requestType == PLRT_O);
size_t len = 1;
status = (*usb_m->send_request)(dev,
list[i].requestType,
list[i].request,
list[i].value,
list[i].index,
0, o?0:buf, o?0:len, &len);
TRACE("usb_send_requ_list: reqs[%d]: %08lx\n", i, status);
}
return B_OK;
}
status_t reset_prolific_device(usb_serial_device *usd){
status_t status;
size_t len = 0;
TRACE_FUNCALLS("> reset_prolific_device(%08x)\n", usd);
status = (*usb_m->send_request)(usd->dev,
/* status = (*usb_m->send_request)(usd->dev,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
PROLIFIC_SET_REQUEST, 0, 0, 0, 0, 0, &len);
*/
usb_send_requ_list(usd->dev, pl_reset_common_reqs, SIZEOF(pl_reset_common_reqs));
if (usd->spec.prolific.is_HX)
usb_send_requ_list(usd->dev, pl_reset_common_hx, SIZEOF(pl_reset_common_hx));
else
usb_send_requ_list(usd->dev, pl_reset_common_nhx, SIZEOF(pl_reset_common_nhx));
TRACE_FUNCRET("< reset_prolific_device returns:%08x\n", status);
return status;
}