1 /*
2 * Copyright (c) 2007-2008 by Michael Lotz
3 * Heavily based on the original usb_serial driver which is:
4 *
5 * Copyright (c) 2003 by Siarzhuk Zharski <imker@gmx.li>
6 * Distributed under the terms of the MIT License.
7 */
8 #include "Prolific.h"
9
ProlificDevice(usb_device device,uint16 vendorID,uint16 productID,const char * description)10 ProlificDevice::ProlificDevice(usb_device device, uint16 vendorID,
11 uint16 productID, const char *description)
12 : ACMDevice(device, vendorID, productID, description),
13 fIsHX(false)
14 {
15 }
16
17
18 status_t
AddDevice(const usb_configuration_info * config)19 ProlificDevice::AddDevice(const usb_configuration_info *config)
20 {
21 TRACE_FUNCALLS("> ProlificDevice::AddDevice(%08x, %08x)\n", this, config);
22
23 // check for device type.
24 // Linux checks for type 0, 1 and HX, but handles 0 and 1 the same.
25 // We'll just check for HX then.
26 const usb_device_descriptor *deviceDescriptor = NULL;
27 deviceDescriptor = gUSBModule->get_device_descriptor(Device());
28 if (deviceDescriptor) {
29 fIsHX = (deviceDescriptor->device_class != 0x02
30 && deviceDescriptor->max_packet_size_0 == 0x40);
31 }
32
33 int32 pipesSet = 0;
34 status_t status = ENODEV;
35 if (config->interface_count > 0) {
36 usb_interface_info *interface = config->interface[0].active;
37 for (size_t i = 0; i < interface->endpoint_count; i++) {
38 usb_endpoint_info *endpoint = &interface->endpoint[i];
39 if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_INTERRUPT) {
40 if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) {
41 SetControlPipe(endpoint->handle);
42 pipesSet++;
43 }
44 }
45 }
46
47 /* They say that USB-RSAQ1 has 2 interfaces */
48 if (config->interface_count >= 2)
49 interface = config->interface[1].active;
50
51 for (size_t i = 0; i < interface->endpoint_count; i++) {
52 usb_endpoint_info *endpoint = &interface->endpoint[i];
53 if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
54 if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
55 SetReadPipe(endpoint->handle);
56 else
57 SetWritePipe(endpoint->handle);
58
59 if (++pipesSet >= 3)
60 break;
61 }
62 }
63
64 if (pipesSet >= 3)
65 status = B_OK;
66 }
67
68 TRACE_FUNCRET("< ProlificDevice::AddDevice() returns: 0x%08x\n", status);
69 return status;
70 }
71
72
73 struct request_item {
74 bool out;
75 uint16 value;
76 uint16 index;
77 };
78
79 /* Linux sends all those, and it seems to work */
80 /* see drivers/usb/serial/pl2303.c */
81 static struct request_item prolific_reset_common[] = {
82 { false, 0x8484, 0 },
83 { true, 0x0404, 0 },
84 { false, 0x8484, 0 },
85 { false, 0x8383, 0 },
86 { false, 0x8484, 0 },
87 { true, 0x0404, 1 },
88 { false, 0x8484, 0 },
89 { false, 0x8383, 0 },
90 { true, 0x0000, 1 },
91 { true, 0x0001, 0 }
92 };
93
94 static struct request_item prolific_reset_common_hx[] = {
95 { true, 2, 0x44 },
96 { true, 8, 0 },
97 { true, 0, 0 }
98 };
99
100 static struct request_item prolific_reset_common_nhx[] = {
101 { true, 2, 0x24 }
102 };
103
104
105 status_t
SendRequestList(request_item * list,size_t length)106 ProlificDevice::SendRequestList(request_item *list, size_t length)
107 {
108 for (size_t i = 0; i < length; i++) {
109 char buffer[10];
110 size_t bufferLength = 1;
111 status_t status = gUSBModule->send_request(Device(),
112 USB_REQTYPE_VENDOR | (list[i].out ? USB_REQTYPE_DEVICE_OUT : USB_REQTYPE_DEVICE_IN),
113 PROLIFIC_SET_REQUEST,
114 list[i].value,
115 list[i].index,
116 list[i].out ? 0 : bufferLength,
117 list[i].out ? NULL : buffer,
118 &bufferLength);
119 TRACE(" ProlificDevice::SendRequestList(): request[%d]: 0x%08lx\n", i, status);
120 if (status != B_OK) {
121 TRACE_ALWAYS("sending request list failed:0x%08lx\n", status);
122 }
123 }
124
125 return B_OK;
126 }
127
128
129 status_t
ResetDevice()130 ProlificDevice::ResetDevice()
131 {
132 TRACE_FUNCALLS("> ProlificDevice::ResetDevice(%08x)\n", this);
133
134 SendRequestList(prolific_reset_common, B_COUNT_OF(prolific_reset_common));
135 if (fIsHX)
136 SendRequestList(prolific_reset_common_hx, B_COUNT_OF(prolific_reset_common_hx));
137 else
138 SendRequestList(prolific_reset_common_nhx, B_COUNT_OF(prolific_reset_common_nhx));
139
140 status_t status = B_OK; /* discard */
141 TRACE_FUNCRET("< ProlificDevice::ResetDevice() returns: 0x%08x\n", status);
142 return status;
143 }
144