1 /*
2 * Copyright 2011, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Alexander von Gluck IV, kallisti5@unixzen.com
7 */
8
9
10 #include "Silicon.h"
11
12
13 static const int kBaudrateGeneratorFrequency = 0x384000;
14
15
SiliconDevice(usb_device device,uint16 vendorID,uint16 productID,const char * description)16 SiliconDevice::SiliconDevice(usb_device device, uint16 vendorID, uint16 productID,
17 const char *description)
18 : SerialDevice(device, vendorID, productID, description)
19 {
20 }
21
22
23 // Called for each configuration of the device. Return B_OK if the given
24 // configuration sounds like it is the usb serial one.
25 status_t
AddDevice(const usb_configuration_info * config)26 SiliconDevice::AddDevice(const usb_configuration_info *config)
27 {
28 status_t status = ENODEV;
29 if (config->interface_count > 0) {
30 int32 pipesSet = 0;
31 usb_interface_info *interface = config->interface[0].active;
32 for (size_t i = 0; i < interface->endpoint_count; i++) {
33 usb_endpoint_info *endpoint = &interface->endpoint[i];
34 if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
35 if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) {
36 SetReadPipe(endpoint->handle);
37 if (++pipesSet >= 3)
38 break;
39 } else {
40 if (endpoint->descr->endpoint_address) {
41 SetControlPipe(endpoint->handle);
42 SetWritePipe(endpoint->handle);
43 pipesSet += 2;
44 if (pipesSet >= 3)
45 break;
46 }
47 }
48 }
49 }
50
51 if (pipesSet >= 3) {
52 status = B_OK;
53 }
54 }
55 return status;
56 }
57
58
59 // Called on opening the device - Good time to enable the UART ?
60 status_t
ResetDevice()61 SiliconDevice::ResetDevice()
62 {
63 uint16_t enableUart = 1;
64 return WriteConfig(ENABLE_UART, &enableUart, 2);
65 }
66
67
68 status_t
SetLineCoding(usb_cdc_line_coding * lineCoding)69 SiliconDevice::SetLineCoding(usb_cdc_line_coding *lineCoding)
70 {
71 uint16_t divider = kBaudrateGeneratorFrequency / lineCoding->speed ;
72 status_t result = WriteConfig(SET_BAUDRATE_DIVIDER, ÷r, 2);
73
74 if (result != B_OK) return result;
75
76 uint16_t data = 0;
77
78 switch (lineCoding->stopbits) {
79 case USB_CDC_LINE_CODING_1_STOPBIT: data = 0; break;
80 case USB_CDC_LINE_CODING_2_STOPBITS: data = 2; break;
81 default:
82 TRACE_ALWAYS("= SiliconDevice::SetLineCoding(): Wrong stopbits param: %d\n",
83 lineCoding->stopbits);
84 break;
85 }
86
87 switch (lineCoding->parity) {
88 case USB_CDC_LINE_CODING_NO_PARITY: data |= 0 << 4; break;
89 case USB_CDC_LINE_CODING_EVEN_PARITY: data |= 2 << 4; break;
90 case USB_CDC_LINE_CODING_ODD_PARITY: data |= 1 << 4; break;
91 default:
92 TRACE_ALWAYS("= SiliconDevice::SetLineCoding(): Wrong parity param: %d\n",
93 lineCoding->parity);
94 break;
95 }
96
97 data |= lineCoding->databits << 8;
98
99 return WriteConfig(SET_LINE_FORMAT, &data, 2);
100 }
101
102
103 status_t
SetControlLineState(uint16 state)104 SiliconDevice::SetControlLineState(uint16 state)
105 {
106 uint16_t control = 0;
107 control |= 0x0300; // We are updating DTR and RTS
108 control |= (state & USB_CDC_CONTROL_SIGNAL_STATE_RTS) ? 2 : 0;
109 control |= (state & USB_CDC_CONTROL_SIGNAL_STATE_DTR) ? 1 : 0;
110
111 return WriteConfig(SET_STATUS, &control, 2);
112 }
113
114
WriteConfig(CP210XRequest request,uint16_t * data,size_t size)115 status_t SiliconDevice::WriteConfig(CP210XRequest request, uint16_t* data,
116 size_t size)
117 {
118 size_t replyLength = 0;
119 status_t result;
120 // Small requests (16 bits and less) use the "value" field for their data.
121 // Bigger ones use the actual buffer.
122 if (size <= 2) {
123 result = gUSBModule->send_request(Device(),
124 USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, request, data[0], 0, 0,
125 NULL, &replyLength);
126 } else {
127 result = gUSBModule->send_request(Device(),
128 USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, request, 0x0000, 0,
129 size, data, &replyLength);
130 }
131
132 if (result != B_OK) {
133 TRACE_ALWAYS("= SiliconDevice request failed: 0x%08x (%s)\n",
134 result, strerror(result));
135 }
136
137 return result;
138 }
139