34#include <sys/eventhandler.h>
35#include <sys/stdint.h>
36#include <sys/stddef.h>
39#include <sys/kernel.h>
41#include <sys/module.h>
44#include <sys/condvar.h>
45#include <sys/sysctl.h>
47#include <sys/unistd.h>
48#include <sys/callout.h>
49#include <sys/malloc.h>
58#define USB_DEBUG_VAR u3g_debug
67static int u3g_debug = 0;
69static SYSCTL_NODE(_hw_usb, OID_AUTO, u3g, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
72 &u3g_debug, 0,
"Debug level");
75#define U3G_MAXPORTS 12
76#define U3G_CONFIG_INDEX 0
78#define U3G_TXSIZE (U3G_BSIZE / U3G_TXFRAMES)
82#define U3GINIT_HUAWEI 1
83#define U3GINIT_SIERRA 2
84#define U3GINIT_SCSIEJECT 3
85#define U3GINIT_REZERO 4
86#define U3GINIT_ZTESTOR 5
87#define U3GINIT_CMOTECH 6
89#define U3GINIT_SAEL_M460 8
90#define U3GINIT_HUAWEISCSI 9
91#define U3GINIT_HUAWEISCSI2 10
149 .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
158 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
166 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
200#define U3G_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
214 U3G_DEV(ANYDATA, ADU_620UW, 0),
215 U3G_DEV(ANYDATA, ADU_E100X, 0),
216 U3G_DEV(AXESSTEL, DATAMODEM, 0),
217 U3G_DEV(CMOTECH, CDMA_MODEM1, 0),
339 U3G_DEV(KYOCERA2, CDMA_MSM_K, 0),
344 U3G_DEV(LONGCHEER, XSSTICK, 0),
398 U3G_DEV(OPTION, GTMAX380HSUPAE, 0),
399 U3G_DEV(OPTION, GTMAXHSUPA, 0),
400 U3G_DEV(OPTION, GTMAXHSUPAE, 0),
401 U3G_DEV(OPTION, VODAFONEMC3G, 0),
402 U3G_DEV(PANASONIC, CFF9_3G_QDL, 0),
403 U3G_DEV(PANASONIC, CFF9_3G, 0),
411 U3G_DEV(QUALCOMM2, SIM5218, 0),
414 U3G_DEV(QUALCOMM2, GOBI2000_QDL, 0),
415 U3G_DEV(QUALCOMM2, GOBI2000, 0),
418 U3G_DEV(QUALCOMMINC, AC2726, 0),
420 U3G_DEV(QUALCOMMINC, AC682, 0),
421 U3G_DEV(QUALCOMMINC, AC8700, 0),
422 U3G_DEV(QUALCOMMINC, AC8710, 0),
424 U3G_DEV(QUALCOMMINC, E0002, 0),
425 U3G_DEV(QUALCOMMINC, E0003, 0),
426 U3G_DEV(QUALCOMMINC, E0004, 0),
427 U3G_DEV(QUALCOMMINC, E0005, 0),
428 U3G_DEV(QUALCOMMINC, E0006, 0),
429 U3G_DEV(QUALCOMMINC, E0007, 0),
430 U3G_DEV(QUALCOMMINC, E0008, 0),
431 U3G_DEV(QUALCOMMINC, E0009, 0),
432 U3G_DEV(QUALCOMMINC, E000A, 0),
433 U3G_DEV(QUALCOMMINC, E000B, 0),
434 U3G_DEV(QUALCOMMINC, E000C, 0),
435 U3G_DEV(QUALCOMMINC, E000D, 0),
436 U3G_DEV(QUALCOMMINC, E000E, 0),
437 U3G_DEV(QUALCOMMINC, E000F, 0),
438 U3G_DEV(QUALCOMMINC, E0010, 0),
439 U3G_DEV(QUALCOMMINC, E0011, 0),
440 U3G_DEV(QUALCOMMINC, E0012, 0),
441 U3G_DEV(QUALCOMMINC, E0013, 0),
442 U3G_DEV(QUALCOMMINC, E0014, 0),
443 U3G_DEV(QUALCOMMINC, E0017, 0),
444 U3G_DEV(QUALCOMMINC, E0018, 0),
445 U3G_DEV(QUALCOMMINC, E0019, 0),
446 U3G_DEV(QUALCOMMINC, E0020, 0),
447 U3G_DEV(QUALCOMMINC, E0021, 0),
448 U3G_DEV(QUALCOMMINC, E0022, 0),
449 U3G_DEV(QUALCOMMINC, E0023, 0),
450 U3G_DEV(QUALCOMMINC, E0024, 0),
451 U3G_DEV(QUALCOMMINC, E0025, 0),
452 U3G_DEV(QUALCOMMINC, E0026, 0),
453 U3G_DEV(QUALCOMMINC, E0027, 0),
454 U3G_DEV(QUALCOMMINC, E0028, 0),
455 U3G_DEV(QUALCOMMINC, E0029, 0),
456 U3G_DEV(QUALCOMMINC, E0030, 0),
457 U3G_DEV(QUALCOMMINC, E0032, 0),
458 U3G_DEV(QUALCOMMINC, E0033, 0),
459 U3G_DEV(QUALCOMMINC, E0037, 0),
460 U3G_DEV(QUALCOMMINC, E0039, 0),
461 U3G_DEV(QUALCOMMINC, E0042, 0),
462 U3G_DEV(QUALCOMMINC, E0043, 0),
463 U3G_DEV(QUALCOMMINC, E0048, 0),
464 U3G_DEV(QUALCOMMINC, E0049, 0),
465 U3G_DEV(QUALCOMMINC, E0051, 0),
466 U3G_DEV(QUALCOMMINC, E0052, 0),
467 U3G_DEV(QUALCOMMINC, E0054, 0),
468 U3G_DEV(QUALCOMMINC, E0055, 0),
469 U3G_DEV(QUALCOMMINC, E0057, 0),
470 U3G_DEV(QUALCOMMINC, E0058, 0),
471 U3G_DEV(QUALCOMMINC, E0059, 0),
472 U3G_DEV(QUALCOMMINC, E0060, 0),
473 U3G_DEV(QUALCOMMINC, E0061, 0),
474 U3G_DEV(QUALCOMMINC, E0062, 0),
475 U3G_DEV(QUALCOMMINC, E0063, 0),
476 U3G_DEV(QUALCOMMINC, E0064, 0),
477 U3G_DEV(QUALCOMMINC, E0066, 0),
478 U3G_DEV(QUALCOMMINC, E0069, 0),
479 U3G_DEV(QUALCOMMINC, E0070, 0),
480 U3G_DEV(QUALCOMMINC, E0073, 0),
481 U3G_DEV(QUALCOMMINC, E0076, 0),
482 U3G_DEV(QUALCOMMINC, E0078, 0),
483 U3G_DEV(QUALCOMMINC, E0082, 0),
484 U3G_DEV(QUALCOMMINC, E0086, 0),
485 U3G_DEV(QUALCOMMINC, SURFSTICK, 0),
486 U3G_DEV(QUALCOMMINC, E2002, 0),
487 U3G_DEV(QUALCOMMINC, E2003, 0),
488 U3G_DEV(QUALCOMMINC, K3772_Z, 0),
491 U3G_DEV(QUALCOMMINC, MF195E, 0),
493 U3G_DEV(QUALCOMMINC, MF626, 0),
494 U3G_DEV(QUALCOMMINC, MF628, 0),
495 U3G_DEV(QUALCOMMINC, MF633R, 0),
523 U3G_DEV(SIERRA, AIRCARD580, 0),
524 U3G_DEV(SIERRA, AIRCARD595, 0),
592 U3G_DEV(WETELECOM, WM_D200, 0),
687 static const uint8_t setup[][24] = {
688 { 0x41, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
689 { 0x41, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
690 { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
691 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
693 { 0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02 },
694 { 0xc1, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 },
695 { 0x41, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
696 { 0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
697 { 0x41, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 },
698 { 0x41, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
699 { 0x41, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 },
700 { 0x41, 0x19, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x11, 0x13 },
702 { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
703 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
704 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00 },
705 { 0x41, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 },
706 { 0x41, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 },
707 { 0x41, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
708 { 0x41, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 },
709 { 0x41, 0x19, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
710 0x00, 0x00, 0x00, 0x00, 0x11, 0x13 },
711 { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
712 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
713 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00 },
714 { 0x41, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
726 DPRINTFN(0,
"Alt setting 0 failed\n");
730 for (
n = 0;
n != nitems(setup);
n++) {
731 memcpy(&
req, setup[
n],
sizeof(
req));
735 if (
len >
sizeof(buf)) {
736 DPRINTFN(0,
"too small buffer\n");
741 if (
len > (
sizeof(setup[0]) - 8)) {
742 DPRINTFN(0,
"too small buffer\n");
746 __DECONST(uint8_t *, &setup[
n][8]));
749 DPRINTFN(1,
"request %u failed\n",
776 unsigned long method;
814 printf(
"Ejecting %s %s using method %ld\n",
870 u3g_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
874 EVENTHANDLER_DEREGISTER(usb_dev_configured,
u3g_etag);
911 uint32_t iface_valid;
929 mtx_init(&sc->
sc_mtx,
"u3g", NULL, MTX_DEF);
944 id->bInterfaceSubClass,
id->bInterfaceProtocol))
947 iface_valid |= (1<<i);
954 if ((iface_valid & (1<<i)) == 0) {
961 u3g_config_tmp[
n].ep_index = ep;
976 sc->
sc_iface[nports] =
id->bInterfaceNumber;
979 device_printf(
dev,
"port %d supports modem control\n",
995 device_printf(
dev,
"no ports found\n");
1003 DPRINTF(
"ucom_attach failed\n");
1031 device_claim_softc(
dev);
1044 mtx_destroy(&sc->
sc_mtx);
1045 device_free_softc(sc);
1185 &
req, NULL, 0, 1000);
1193 DPRINTF(
"onoff = %d\n", onoff);
1208 DPRINTF(
"onoff = %d\n", onoff);
1234 DPRINTF(
"message too short (expected 8, received %d)\n", actlen);
1242 DPRINTF(
"message too short (expected 2 data bytes, received %d)\n", wLen);
1252 DPRINTF(
"notify bytes = 0x%02x, 0x%02x\n",
1259 mstatus = pkt.
data[0];
static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB DWC OTG")
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN, &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+")
uint16_t sc_line[U3G_MAXPORTS]
struct ucom_super_softc sc_super_ucom
uint8_t sc_lsr[U3G_MAXPORTS]
struct usb_device * sc_udev
uint8_t sc_iface[U3G_MAXPORTS]
uint8_t sc_msr[U3G_MAXPORTS]
struct usb_xfer * sc_xfer[U3G_MAXPORTS][U3G_N_TRANSFER]
struct ucom_softc sc_ucom[U3G_MAXPORTS]
void(* ucom_cfg_get_status)(struct ucom_softc *, uint8_t *plsr, uint8_t *pmsr)
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
struct usb_interface_descriptor * idesc
uint8_t bInterfaceSubClass
uint8_t bInterfaceProtocol
static void u3g_cfg_set_line(struct ucom_softc *ucom)
static usb_callback_t u3g_intr_callback
static device_probe_t u3g_probe
static const struct ucom_callback u3g_callback
static driver_t u3g_driver
static device_detach_t u3g_detach
static void u3g_stop_write(struct ucom_softc *ucom)
static usb_callback_t u3g_read_callback
USB_PNP_HOST_INFO(u3g_devs)
static void u3g_sael_m460_init(struct usb_device *udev)
#define U3GINIT_SCSIEJECT
#define U3GINIT_HUAWEISCSI
static const struct usb_config u3g_config[U3G_N_TRANSFER]
static void u3g_free(struct ucom_softc *ucom)
static int u3g_sierra_init(struct usb_device *udev)
static void u3g_test_autoinst(void *, struct usb_device *, struct usb_attach_arg *)
static void u3g_cfg_set_rts(struct ucom_softc *, uint8_t)
static void u3g_cfg_set_dtr(struct ucom_softc *, uint8_t)
static void u3g_start_read(struct ucom_softc *ucom)
static const STRUCT_USB_HOST_ID u3g_devs[]
static devclass_t u3g_devclass
static int u3g_driver_loaded(struct module *mod, int what, void *arg)
static void u3g_free_softc(struct u3g_softc *)
static int u3g_huawei_init(struct usb_device *udev)
static void u3g_start_write(struct ucom_softc *ucom)
static int u3g_huawei_is_cdce(uint16_t idVendor, uint8_t bInterfaceSubClass, uint8_t bInterfaceProtocol)
MODULE_DEPEND(u3g, ucom, 1, 1, 1)
static eventhandler_tag u3g_etag
static device_attach_t u3g_attach
static device_method_t u3g_methods[]
static void u3g_stop_read(struct ucom_softc *ucom)
#define U3GINIT_SAEL_M460
#define U3GINIT_HUAWEISCSI2
static usb_callback_t u3g_write_callback
static void u3g_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *)
static void u3g_poll(struct ucom_softc *ucom)
DRIVER_MODULE(u3g, uhub, u3g_driver, u3g_devclass, u3g_driver_loaded, 0)
#define UF_DEVICE_REMOTE_WAKEUP
#define UT_WRITE_CLASS_INTERFACE
#define UHF_PORT_CONNECTION
void usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset, void *ptr, usb_frlength_t len)
#define UCDC_N_SERIAL_STATE
#define UCDC_N_SERIAL_DCD
#define UCDC_SET_CONTROL_LINE_STATE
#define UCDC_N_SERIAL_DSR
#define UCDC_NOTIFICATION
struct usb_interface_descriptor * usbd_get_interface_descriptor(struct usb_interface *iface)
void usbd_set_parent_iface(struct usb_device *udev, uint8_t iface_index, uint8_t parent_index)
const char * usb_get_product(struct usb_device *udev)
struct usb_interface * usbd_get_iface(struct usb_device *udev, uint8_t iface_index)
const char * usb_get_manufacturer(struct usb_device *udev)
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
usb_error_t usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
@ UQ_MSC_EJECT_HUAWEISCSI
@ UQ_MSC_EJECT_HUAWEISCSI2
uint8_t usb_test_quirk(const struct usb_attach_arg *uaa, uint16_t quirk)
usb_error_t usbd_req_set_alt_interface_no(struct usb_device *udev, struct mtx *mtx, uint8_t iface_index, uint8_t alt_no)
usb_error_t usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, struct usb_device_request *req, void *data, uint16_t flags, uint16_t *actlen, usb_timeout_t timeout)
uint8_t ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc, uint32_t offset, uint32_t len, uint32_t *actlen)
void ucom_status_change(struct ucom_softc *sc)
int ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc, int subunits, void *parent, const struct ucom_callback *callback, struct mtx *mtx)
int ucom_unref(struct ucom_super_softc *ssc)
void ucom_ref(struct ucom_super_softc *ssc)
void ucom_set_pnpinfo_usb(struct ucom_super_softc *ssc, device_t dev)
void ucom_detach(struct ucom_super_softc *ssc, struct ucom_softc *sc)
void ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc, uint32_t offset, uint32_t len)
#define ucom_cfg_do_request(udev, com, req, ptr, flags, timo)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void usbd_xfer_set_frame_offset(struct usb_xfer *xfer, usb_frlength_t offset, usb_frcount_t frindex)
void usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
usb_frlength_t usbd_xfer_max_len(struct usb_xfer *xfer)
void device_set_usb_desc(device_t dev)
uint8_t bInterfaceSubClass
uint8_t bInterfaceProtocol
#define USB_ST_TRANSFERRED
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define STRUCT_USB_HOST_ID
#define USB_GET_DRIVER_INFO(did)
#define USB_GET_STATE(xfer)
#define usbd_do_request(u, m, r, d)