usb_template_modem.c revision 331722
1/* $FreeBSD: stable/11/sys/dev/usb/template/usb_template_modem.c 331722 2018-03-29 02:50:57Z eadler $ */
2/*-
3 * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * This file contains the USB template for an USB Modem Device.
29 */
30
31#ifdef USB_GLOBAL_INCLUDE_FILE
32#include USB_GLOBAL_INCLUDE_FILE
33#else
34#include <sys/stdint.h>
35#include <sys/stddef.h>
36#include <sys/param.h>
37#include <sys/queue.h>
38#include <sys/types.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/bus.h>
42#include <sys/module.h>
43#include <sys/lock.h>
44#include <sys/mutex.h>
45#include <sys/condvar.h>
46#include <sys/sysctl.h>
47#include <sys/sx.h>
48#include <sys/unistd.h>
49#include <sys/callout.h>
50#include <sys/malloc.h>
51#include <sys/priv.h>
52
53#include <dev/usb/usb.h>
54#include <dev/usb/usbdi.h>
55#include <dev/usb/usb_core.h>
56#include <dev/usb/usb_cdc.h>
57
58#include <dev/usb/template/usb_template.h>
59#endif			/* USB_GLOBAL_INCLUDE_FILE */
60
61enum {
62	INDEX_LANG,
63	INDEX_MODEM,
64	INDEX_PRODUCT,
65	INDEX_MAX,
66};
67
68#define	STRING_PRODUCT \
69  "M\0o\0d\0e\0m\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
70
71#define	STRING_MODEM \
72  "M\0o\0d\0e\0m\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
73
74/* make the real string descriptors */
75
76USB_MAKE_STRING_DESC(STRING_MODEM, string_modem);
77USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product);
78
79#define	MODEM_IFACE_0 0
80#define	MODEM_IFACE_1 1
81
82/* prototypes */
83
84static const struct usb_temp_packet_size modem_bulk_mps = {
85	.mps[USB_SPEED_LOW] = 8,
86	.mps[USB_SPEED_FULL] = 64,
87	.mps[USB_SPEED_HIGH] = 512,
88};
89
90static const struct usb_temp_packet_size modem_intr_mps = {
91	.mps[USB_SPEED_LOW] = 8,
92	.mps[USB_SPEED_FULL] = 8,
93	.mps[USB_SPEED_HIGH] = 8,
94};
95
96static const struct usb_temp_interval modem_intr_interval = {
97	.bInterval[USB_SPEED_LOW] = 8,	/* 8ms */
98	.bInterval[USB_SPEED_FULL] = 8,	/* 8ms */
99	.bInterval[USB_SPEED_HIGH] = 7,	/* 8ms */
100};
101
102static const struct usb_temp_endpoint_desc modem_ep_0 = {
103	.pPacketSize = &modem_intr_mps,
104	.pIntervals = &modem_intr_interval,
105	.bEndpointAddress = UE_DIR_IN,
106	.bmAttributes = UE_INTERRUPT,
107};
108
109static const struct usb_temp_endpoint_desc modem_ep_1 = {
110	.pPacketSize = &modem_bulk_mps,
111	.bEndpointAddress = UE_DIR_OUT,
112	.bmAttributes = UE_BULK,
113};
114
115static const struct usb_temp_endpoint_desc modem_ep_2 = {
116	.pPacketSize = &modem_bulk_mps,
117	.bEndpointAddress = UE_DIR_IN,
118	.bmAttributes = UE_BULK,
119};
120
121static const struct usb_temp_endpoint_desc *modem_iface_0_ep[] = {
122	&modem_ep_0,
123	NULL,
124};
125
126static const struct usb_temp_endpoint_desc *modem_iface_1_ep[] = {
127	&modem_ep_1,
128	&modem_ep_2,
129	NULL,
130};
131
132static const uint8_t modem_raw_desc_0[] = {
133	0x05, 0x24, 0x00, 0x10, 0x01
134};
135
136static const uint8_t modem_raw_desc_1[] = {
137	0x05, 0x24, 0x06, MODEM_IFACE_0, MODEM_IFACE_1
138};
139
140static const uint8_t modem_raw_desc_2[] = {
141	0x05, 0x24, 0x01, 0x03, MODEM_IFACE_1
142};
143
144static const uint8_t modem_raw_desc_3[] = {
145	0x04, 0x24, 0x02, 0x07
146};
147
148static const void *modem_iface_0_desc[] = {
149	&modem_raw_desc_0,
150	&modem_raw_desc_1,
151	&modem_raw_desc_2,
152	&modem_raw_desc_3,
153	NULL,
154};
155
156static const struct usb_temp_interface_desc modem_iface_0 = {
157	.ppRawDesc = modem_iface_0_desc,
158	.ppEndpoints = modem_iface_0_ep,
159	.bInterfaceClass = 2,
160	.bInterfaceSubClass = 2,
161	.bInterfaceProtocol = 1,
162	.iInterface = INDEX_MODEM,
163};
164
165static const struct usb_temp_interface_desc modem_iface_1 = {
166	.ppEndpoints = modem_iface_1_ep,
167	.bInterfaceClass = 10,
168	.bInterfaceSubClass = 0,
169	.bInterfaceProtocol = 0,
170	.iInterface = INDEX_MODEM,
171};
172
173static const struct usb_temp_interface_desc *modem_interfaces[] = {
174	&modem_iface_0,
175	&modem_iface_1,
176	NULL,
177};
178
179static const struct usb_temp_config_desc modem_config_desc = {
180	.ppIfaceDesc = modem_interfaces,
181	.bmAttributes = UC_BUS_POWERED,
182	.bMaxPower = 25,		/* 50 mA */
183	.iConfiguration = INDEX_PRODUCT,
184};
185
186static const struct usb_temp_config_desc *modem_configs[] = {
187	&modem_config_desc,
188	NULL,
189};
190
191static usb_temp_get_string_desc_t modem_get_string_desc;
192static usb_temp_get_vendor_desc_t modem_get_vendor_desc;
193
194const struct usb_temp_device_desc usb_template_modem = {
195	.getStringDesc = &modem_get_string_desc,
196	.getVendorDesc = &modem_get_vendor_desc,
197	.ppConfigDesc = modem_configs,
198	.idVendor = USB_TEMPLATE_VENDOR,
199	.idProduct = 0x000E,
200	.bcdDevice = 0x0100,
201	.bDeviceClass = UDCLASS_COMM,
202	.bDeviceSubClass = 0,
203	.bDeviceProtocol = 0,
204	.iManufacturer = 0,
205	.iProduct = INDEX_PRODUCT,
206	.iSerialNumber = 0,
207};
208
209/*------------------------------------------------------------------------*
210 *      modem_get_vendor_desc
211 *
212 * Return values:
213 * NULL: Failure. No such vendor descriptor.
214 * Else: Success. Pointer to vendor descriptor is returned.
215 *------------------------------------------------------------------------*/
216static const void *
217modem_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen)
218{
219	return (NULL);
220}
221
222/*------------------------------------------------------------------------*
223 *	modem_get_string_desc
224 *
225 * Return values:
226 * NULL: Failure. No such string.
227 * Else: Success. Pointer to string descriptor is returned.
228 *------------------------------------------------------------------------*/
229static const void *
230modem_get_string_desc(uint16_t lang_id, uint8_t string_index)
231{
232	static const void *ptr[INDEX_MAX] = {
233		[INDEX_LANG] = &usb_string_lang_en,
234		[INDEX_MODEM] = &string_modem,
235		[INDEX_PRODUCT] = &string_product,
236	};
237
238	if (string_index == 0) {
239		return (&usb_string_lang_en);
240	}
241	if (lang_id != 0x0409) {
242		return (NULL);
243	}
244	if (string_index < INDEX_MAX) {
245		return (ptr[string_index]);
246	}
247	return (NULL);
248}
249