The Pedigree Project 0.1
FtdiSerialDevice.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "FtdiSerialDevice.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/utilities/PointerGuard.h"
23#include "pedigree/kernel/utilities/Vector.h"
24#include "pedigree/kernel/utilities/new"
25
26#include "modules/system/usb/UsbConstants.h"
27#include "modules/system/usb/UsbDevice.h"
28
29#define FTDI_BAUD_RATE 9600
30
31static uint8_t nSubdivisors[8] = {0, 3, 2, 4, 1, 5, 6, 7};
32
33FtdiSerialDevice::FtdiSerialDevice(UsbDevice* dev)
34 : UsbDevice(dev), Serial(), m_pInEndpoint(0), m_pOutEndpoint(0) {}
35
36FtdiSerialDevice::~FtdiSerialDevice() {}
37
39 // Reset the device
40 controlRequest(UsbRequestType::Vendor, 0, 0, 0);
41
42 // Calculate the divisor and subdivisor for the baud rate
43 uint16_t nDivisor = (48000000 / 2) / FTDI_BAUD_RATE, nSubdivisor = nSubdivisors[nDivisor % 8];
44 nDivisor /= 8;
45
46 // Set the divisor and subdivisor (0x4138 / 0x00 for 9600)
47 controlRequest(UsbRequestType::Vendor, 3, (nSubdivisor & 3) << 14 | nDivisor, nSubdivisor >> 2);
48
49 // Get the in and out endpoints
50 for (size_t i = 0; i < m_pInterface->endpointList.count(); i++) {
51 Endpoint* pEndpoint = m_pInterface->endpointList[i];
52 if (!m_pInEndpoint && (pEndpoint->nTransferType == Endpoint::Bulk) && pEndpoint->bIn)
53 m_pInEndpoint = pEndpoint;
54 if (!m_pOutEndpoint && (pEndpoint->nTransferType == Endpoint::Bulk) && pEndpoint->bOut)
55 m_pOutEndpoint = pEndpoint;
56 if (m_pInEndpoint && m_pOutEndpoint)
57 break;
58 }
59
60 if (!m_pInEndpoint) {
61 ERROR("USB: FTDI: No IN endpoint");
62 return;
63 }
64
65 if (!m_pOutEndpoint) {
66 ERROR("USB: FTDI: No OUT endpoint");
67 return;
68 }
69
70 m_UsbState = HasDriver;
71}
72
73char FtdiSerialDevice::read() {
74 char* pChar = new char(0);
75 PointerGuard<char> guard(pChar);
76 syncIn(m_pInEndpoint, reinterpret_cast<uintptr_t>(pChar), 1);
77 return *pChar;
78}
79
80void FtdiSerialDevice::write(char c) {
81 char* pChar = new char(c);
82 PointerGuard<char> guard(pChar);
83 syncOut(m_pOutEndpoint, reinterpret_cast<uintptr_t>(pChar), 1);
84}
virtual void initialiseDriver()
Implemented by the driver class, initialises driver-specific stuff.
Interface * m_pInterface
Interface in use.
Definition UsbDevice.h:320
bool controlRequest(uint8_t nRequestType, uint8_t nRequest, uint16_t nValue, uint16_t nIndex, uint16_t nLength=0, uintptr_t pBuffer=0, uint32_t timeout=5000)
Performs an USB control request.
Definition UsbDevice.cc:558
UsbState m_UsbState
The current state of the device.
Definition UsbDevice.h:311