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 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 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 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 130 ProlificDevice::ResetDevice() 131 { 132 TRACE_FUNCALLS("> ProlificDevice::ResetDevice(%08x)\n", this); 133 134 SendRequestList(prolific_reset_common, SIZEOF(prolific_reset_common)); 135 if (fIsHX) 136 SendRequestList(prolific_reset_common_hx, SIZEOF(prolific_reset_common_hx)); 137 else 138 SendRequestList(prolific_reset_common_nhx, SIZEOF(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