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 "KLSI.h" 9 #include <ByteOrder.h> 10 11 KLSIDevice::KLSIDevice(usb_device device, uint16 vendorID, uint16 productID, 12 const char *description) 13 : SerialDevice(device, vendorID, productID, description) 14 { 15 } 16 17 18 status_t 19 KLSIDevice::AddDevice(const usb_configuration_info *config) 20 { 21 TRACE_FUNCALLS("> KLSIDevice::AddDevice(%08x, %08x)\n", this, config); 22 23 int32 pipesSet = 0; 24 status_t status = ENODEV; 25 if (config->interface_count > 0) { 26 usb_interface_info *interface = config->interface[0].active; 27 for (size_t i = 0; i < interface->endpoint_count; i++) { 28 usb_endpoint_info *endpoint = &interface->endpoint[i]; 29 if (endpoint->descr->attributes == USB_EP_ATTR_INTERRUPT) { 30 if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) { 31 SetControlPipe(endpoint->handle); 32 if (++pipesSet >= 3) 33 break; 34 } 35 } else if (endpoint->descr->attributes == USB_EP_ATTR_BULK) { 36 if (endpoint->descr->endpoint_address & USB_EP_ADDR_DIR_IN) { 37 SetReadPipe(endpoint->handle); 38 if (++pipesSet >= 3) 39 break; 40 } else { 41 SetWritePipe(endpoint->handle); 42 if (++pipesSet >= 3) 43 break; 44 } 45 } 46 } 47 } 48 49 if (pipesSet >= 3) 50 status = B_OK; 51 52 TRACE_FUNCRET("< KLSIDevice::AddDevice() returns: 0x%08x\n", status); 53 return status; 54 } 55 56 57 status_t 58 KLSIDevice::ResetDevice() 59 { 60 TRACE_FUNCALLS("> KLSIDevice::ResetDevice(%08x)\n", this); 61 62 size_t length = 0; 63 status_t status = gUSBModule->send_request(Device(), 64 USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT, 65 KLSI_CONF_REQUEST, 66 KLSI_CONF_REQUEST_READ_ON, 0, 0, NULL, &length); 67 68 TRACE_FUNCRET("< KLSIDevice::ResetDevice() returns: 0x%08x\n", status); 69 return status; 70 } 71 72 73 status_t 74 KLSIDevice::SetLineCoding(usb_serial_line_coding *lineCoding) 75 { 76 TRACE_FUNCALLS("> KLSIDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n", 77 this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity, 78 lineCoding->databits); 79 80 uint8 rate; 81 switch (lineCoding->speed) { 82 case 300: rate = klsi_sio_b300; break; 83 case 600: rate = klsi_sio_b600; break; 84 case 1200: rate = klsi_sio_b1200; break; 85 case 2400: rate = klsi_sio_b2400; break; 86 case 4800: rate = klsi_sio_b4800; break; 87 case 9600: rate = klsi_sio_b9600; break; 88 case 19200: rate = klsi_sio_b19200; break; 89 case 38400: rate = klsi_sio_b38400; break; 90 case 57600: rate = klsi_sio_b57600; break; 91 case 115200: rate = klsi_sio_b115200; break; 92 default: 93 rate = klsi_sio_b19200; 94 TRACE_ALWAYS("= KLSIDevice::SetLineCoding(): Datarate: %d is not " 95 "supported by this hardware. Defaulted to %d\n", 96 lineCoding->speed, rate); 97 break; 98 } 99 100 uint8 codingPacket[5]; 101 codingPacket[0] = 5; /* size */ 102 codingPacket[1] = rate; 103 codingPacket[2] = lineCoding->databits; /* only 7,8 */ 104 codingPacket[3] = 0; /* unknown */ 105 codingPacket[4] = 1; /* unknown */ 106 107 size_t length = 0; 108 status_t status = gUSBModule->send_request(Device(), 109 USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT, 110 KLSI_SET_REQUEST, 0, 0, 111 sizeof(codingPacket), codingPacket, &length); 112 113 if (status != B_OK) 114 TRACE_ALWAYS("= KLSIDevice::SetLineCoding(): datarate set request failed: 0x%08x\n", status); 115 116 TRACE_FUNCRET("< KLSIDevice::SetLineCoding() returns: 0x%08x\n", status); 117 return status; 118 } 119 120 121 void 122 KLSIDevice::OnRead(char **buffer, size_t *numBytes) 123 { 124 if (*numBytes <= 2) { 125 *numBytes = 0; 126 return; 127 } 128 129 size_t bytes = B_LENDIAN_TO_HOST_INT16(*(uint16 *)(*buffer)); 130 *numBytes = MIN(bytes, *numBytes - 2); 131 *buffer += 2; 132 } 133 134 135 void 136 KLSIDevice::OnWrite(const char *buffer, size_t *numBytes) 137 { 138 if (*numBytes >= WriteBufferSize() - 2) 139 *numBytes = WriteBufferSize() - 2; 140 141 char *writeBuffer = WriteBuffer(); 142 *((uint16 *)writeBuffer) = B_HOST_TO_LENDIAN_INT16(*numBytes); 143 memcpy(writeBuffer + 2, buffer, *numBytes); 144 *numBytes += 2; 145 } 146 147 148 void 149 KLSIDevice::OnClose() 150 { 151 TRACE_FUNCALLS("> KLSIDevice::OnClose(%08x)\n", this); 152 153 size_t length = 0; 154 status_t status = gUSBModule->send_request(Device(), 155 USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, 156 KLSI_CONF_REQUEST, 157 KLSI_CONF_REQUEST_READ_OFF, 0, 0, 158 NULL, &length); 159 160 TRACE_FUNCRET("< KLSIDevice::OnClose() returns: 0x%08x\n", status); 161 } 162